61 |
|
* shutdown, a new one will take its place if needed to execute |
62 |
|
* subsequent tasks.) Tasks are guaranteed to execute |
63 |
|
* sequentially, and no more than one task will be active at any |
64 |
< |
* given time. The returned executor cannot be reconfigured |
65 |
< |
* to use additional threads. |
64 |
> |
* given time. Unlike the otherwise equivalent |
65 |
> |
* <tt>newFixedThreadPool(1)</tt> the returned executor is |
66 |
> |
* guaranteed not to be reconfigurable to use additional threads. |
67 |
|
* |
68 |
|
* @return the newly-created single-threaded Executor |
69 |
|
*/ |
70 |
|
public static ExecutorService newSingleThreadExecutor() { |
71 |
< |
return unconfigurableExecutorService |
71 |
> |
return new DelegatedExecutorService |
72 |
|
(new ThreadPoolExecutor(1, 1, |
73 |
|
0L, TimeUnit.MILLISECONDS, |
74 |
|
new LinkedBlockingQueue<Runnable>())); |
78 |
|
* Creates an Executor that uses a single worker thread operating |
79 |
|
* off an unbounded queue, and uses the provided ThreadFactory to |
80 |
|
* create a new thread when needed. Unlike the otherwise |
81 |
< |
* equivalent <tt>newFixedThreadPool(1)</tt> the returned executor |
81 |
> |
* equivalent <tt>newFixedThreadPool(1, threadFactory)</tt> the returned executor |
82 |
|
* is guaranteed not to be reconfigurable to use additional |
83 |
|
* threads. |
84 |
|
* |
88 |
|
* @return the newly-created single-threaded Executor |
89 |
|
*/ |
90 |
|
public static ExecutorService newSingleThreadExecutor(ThreadFactory threadFactory) { |
91 |
< |
return unconfigurableExecutorService |
91 |
> |
return new DelegatedExecutorService |
92 |
|
(new ThreadPoolExecutor(1, 1, |
93 |
|
0L, TimeUnit.MILLISECONDS, |
94 |
|
new LinkedBlockingQueue<Runnable>(), |
133 |
|
} |
134 |
|
|
135 |
|
/** |
136 |
< |
* Creates a thread pool that can schedule commands to run after a |
137 |
< |
* given delay, or to execute periodically. |
138 |
< |
* @return a newly created scheduled thread pool with termination management |
136 |
> |
* Creates a single-threaded executor that can schedule commands |
137 |
> |
* to run after a given delay, or to execute periodically. |
138 |
> |
* (Note however that if this single |
139 |
> |
* thread terminates due to a failure during execution prior to |
140 |
> |
* shutdown, a new one will take its place if needed to execute |
141 |
> |
* subsequent tasks.) Tasks are guaranteed to execute |
142 |
> |
* sequentially, and no more than one task will be active at any |
143 |
> |
* given time. Unlike the otherwise equivalent |
144 |
> |
* <tt>newScheduledThreadPool(1)</tt> the returned executor is |
145 |
> |
* guaranteed not to be reconfigurable to use additional threads. |
146 |
> |
* @return a newly created scheduled executor |
147 |
> |
*/ |
148 |
> |
public static ScheduledExecutorService newSingleThreadScheduledExecutor() { |
149 |
> |
return new DelegatedScheduledExecutorService |
150 |
> |
(new ScheduledThreadPoolExecutor(1)); |
151 |
> |
} |
152 |
> |
|
153 |
> |
/** |
154 |
> |
* Creates a single-threaded executor that can schedule commands |
155 |
> |
* to run after a given delay, or to execute periodically. (Note |
156 |
> |
* however that if this single thread terminates due to a failure |
157 |
> |
* during execution prior to shutdown, a new one will take its |
158 |
> |
* place if needed to execute subsequent tasks.) Tasks are |
159 |
> |
* guaranteed to execute sequentially, and no more than one task |
160 |
> |
* will be active at any given time. Unlike the otherwise |
161 |
> |
* equivalent <tt>newScheduledThreadPool(1, threadFactory)</tt> |
162 |
> |
* the returned executor is guaranteed not to be reconfigurable to |
163 |
> |
* use additional threads. |
164 |
> |
* @param threadFactory the factory to use when creating new |
165 |
> |
* threads |
166 |
> |
* @return a newly created scheduled executor |
167 |
|
*/ |
168 |
< |
public static ScheduledExecutorService newScheduledThreadPool() { |
169 |
< |
return newScheduledThreadPool(1); |
168 |
> |
public static ScheduledExecutorService newSingleThreadScheduledExecutor(ThreadFactory threadFactory) { |
169 |
> |
return new DelegatedScheduledExecutorService |
170 |
> |
(new ScheduledThreadPoolExecutor(1, threadFactory)); |
171 |
|
} |
172 |
|
|
173 |
|
/** |
175 |
|
* given delay, or to execute periodically. |
176 |
|
* @param corePoolSize the number of threads to keep in the pool, |
177 |
|
* even if they are idle. |
178 |
< |
* @return a newly created scheduled thread pool with termination management |
178 |
> |
* @return a newly created scheduled thread pool |
179 |
|
*/ |
180 |
|
public static ScheduledExecutorService newScheduledThreadPool(int corePoolSize) { |
181 |
|
return new ScheduledThreadPoolExecutor(corePoolSize); |
188 |
|
* even if they are idle. |
189 |
|
* @param threadFactory the factory to use when the executor |
190 |
|
* creates a new thread. |
191 |
< |
* @return a newly created scheduled thread pool with termination management |
191 |
> |
* @return a newly created scheduled thread pool |
192 |
|
*/ |
193 |
|
public static ScheduledExecutorService newScheduledThreadPool( |
194 |
|
int corePoolSize, ThreadFactory threadFactory) { |
278 |
|
* @throws AccessControlException if the current access control |
279 |
|
* context does not have permission to both get and set context |
280 |
|
* class loader. |
251 |
– |
* @see PrivilegedFutureTask |
281 |
|
*/ |
282 |
|
public static ThreadFactory privilegedThreadFactory() { |
283 |
|
return new PrivilegedThreadFactory(); |
360 |
|
return new PrivilegedCallableUsingCurrentClassLoader(callable); |
361 |
|
} |
362 |
|
|
363 |
+ |
// Non-public classes supporting the public methods |
364 |
|
|
365 |
|
/** |
366 |
|
* A callable that runs given task and returns given result |
411 |
|
static class PrivilegedCallable<T> implements Callable<T> { |
412 |
|
private final AccessControlContext acc; |
413 |
|
private final Callable<T> task; |
414 |
< |
T result; |
415 |
< |
Exception exception; |
414 |
> |
private T result; |
415 |
> |
private Exception exception; |
416 |
|
PrivilegedCallable(Callable<T> task) { |
417 |
|
this.task = task; |
418 |
|
this.acc = AccessController.getContext(); |
444 |
|
private final ClassLoader ccl; |
445 |
|
private final AccessControlContext acc; |
446 |
|
private final Callable<T> task; |
447 |
< |
T result; |
448 |
< |
Exception exception; |
447 |
> |
private T result; |
448 |
> |
private Exception exception; |
449 |
|
PrivilegedCallableUsingCurrentClassLoader(Callable<T> task) { |
450 |
|
this.task = task; |
451 |
|
this.ccl = Thread.currentThread().getContextClassLoader(); |
482 |
|
} |
483 |
|
} |
484 |
|
|
485 |
+ |
/** |
486 |
+ |
* The default thread factory |
487 |
+ |
*/ |
488 |
|
static class DefaultThreadFactory implements ThreadFactory { |
489 |
|
static final AtomicInteger poolNumber = new AtomicInteger(1); |
490 |
|
final ThreadGroup group; |
512 |
|
} |
513 |
|
} |
514 |
|
|
515 |
+ |
/** |
516 |
+ |
* Thread factory capturing access control and class loader |
517 |
+ |
*/ |
518 |
|
static class PrivilegedThreadFactory extends DefaultThreadFactory { |
519 |
|
private final ClassLoader ccl; |
520 |
|
private final AccessControlContext acc; |