1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 package org.eclipse.jetty.util.thread;
20
21 import java.io.IOException;
22 import java.util.Arrays;
23 import java.util.List;
24 import java.util.concurrent.ScheduledFuture;
25 import java.util.concurrent.ScheduledThreadPoolExecutor;
26 import java.util.concurrent.ThreadFactory;
27 import java.util.concurrent.TimeUnit;
28
29 import org.eclipse.jetty.util.component.AbstractLifeCycle;
30 import org.eclipse.jetty.util.component.ContainerLifeCycle;
31 import org.eclipse.jetty.util.component.Dumpable;
32
33
34
35
36
37
38
39
40
41 public class ScheduledExecutorScheduler extends AbstractLifeCycle implements Scheduler, Dumpable
42 {
43 private final String name;
44 private final boolean daemon;
45 private final ClassLoader classloader;
46 private final ThreadGroup threadGroup;
47 private volatile ScheduledThreadPoolExecutor scheduler;
48 private volatile Thread thread;
49
50 public ScheduledExecutorScheduler()
51 {
52 this(null, false);
53 }
54
55 public ScheduledExecutorScheduler(String name, boolean daemon)
56 {
57 this (name,daemon, Thread.currentThread().getContextClassLoader());
58 }
59
60 public ScheduledExecutorScheduler(String name, boolean daemon, ClassLoader threadFactoryClassLoader)
61 {
62 this(name, daemon, threadFactoryClassLoader, null);
63 }
64
65 public ScheduledExecutorScheduler(String name, boolean daemon, ClassLoader threadFactoryClassLoader, ThreadGroup threadGroup)
66 {
67 this.name = name == null ? "Scheduler-" + hashCode() : name;
68 this.daemon = daemon;
69 this.classloader = threadFactoryClassLoader == null ? Thread.currentThread().getContextClassLoader() : threadFactoryClassLoader;
70 this.threadGroup = threadGroup;
71 }
72
73 @Override
74 protected void doStart() throws Exception
75 {
76 scheduler = new ScheduledThreadPoolExecutor(1, new ThreadFactory()
77 {
78 @Override
79 public Thread newThread(Runnable r)
80 {
81 Thread thread = ScheduledExecutorScheduler.this.thread = new Thread(threadGroup, r, name);
82 thread.setDaemon(daemon);
83 thread.setContextClassLoader(classloader);
84 return thread;
85 }
86 });
87 scheduler.setRemoveOnCancelPolicy(true);
88 super.doStart();
89 }
90
91 @Override
92 protected void doStop() throws Exception
93 {
94 scheduler.shutdownNow();
95 super.doStop();
96 scheduler = null;
97 }
98
99 @Override
100 public Task schedule(Runnable task, long delay, TimeUnit unit)
101 {
102 ScheduledThreadPoolExecutor s = scheduler;
103 if (s==null)
104 return new Task(){
105 @Override
106 public boolean cancel()
107 {
108 return false;
109 }};
110
111 ScheduledFuture<?> result = s.schedule(task, delay, unit);
112 return new ScheduledFutureTask(result);
113 }
114
115 @Override
116 public String dump()
117 {
118 return ContainerLifeCycle.dump(this);
119 }
120
121 @Override
122 public void dump(Appendable out, String indent) throws IOException
123 {
124 ContainerLifeCycle.dumpObject(out, this);
125 Thread thread = this.thread;
126 if (thread != null)
127 {
128 List<StackTraceElement> frames = Arrays.asList(thread.getStackTrace());
129 ContainerLifeCycle.dump(out, indent, frames);
130 }
131 }
132
133 private static class ScheduledFutureTask implements Task
134 {
135 private final ScheduledFuture<?> scheduledFuture;
136
137 ScheduledFutureTask(ScheduledFuture<?> scheduledFuture)
138 {
139 this.scheduledFuture = scheduledFuture;
140 }
141
142 @Override
143 public boolean cancel()
144 {
145 return scheduledFuture.cancel(false);
146 }
147 }
148 }