76 |
|
* be in the same {@link ThreadGroup} and with the same |
77 |
|
* <tt>NORM_PRIORITY</tt> priority and non-daemon status. By supplying |
78 |
|
* a different ThreadFactory, you can alter the thread's name, thread |
79 |
< |
* group, priority, daemon status, etc. </dd> |
79 |
> |
* group, priority, daemon status, etc. If a ThreadFactory fails to create |
80 |
> |
* a thread when asked (i.e., if it returns <tt>null</tt> or throws |
81 |
> |
* a <tt>RuntimeException</tt>), the executor will continue, but might |
82 |
> |
* not be able to execute any tasks. </dd> |
83 |
|
* |
84 |
|
* <dt>Keep-alive times</dt> |
85 |
|
* |
384 |
|
* task. Call only while holding mainLock |
385 |
|
* @param firstTask the task the new thread should run first (or |
386 |
|
* null if none) |
387 |
< |
* @return the new thread |
387 |
> |
* @return the new thread, or null if threadFactory fails to create thread |
388 |
|
*/ |
389 |
|
private Thread addThread(Runnable firstTask) { |
390 |
|
Worker w = new Worker(firstTask); |
391 |
< |
Thread t = threadFactory.newThread(w); |
392 |
< |
w.thread = t; |
393 |
< |
workers.add(w); |
394 |
< |
int nt = ++poolSize; |
395 |
< |
if (nt > largestPoolSize) |
396 |
< |
largestPoolSize = nt; |
391 |
> |
Thread t = null; |
392 |
> |
try { |
393 |
> |
t = threadFactory.newThread(w); |
394 |
> |
} |
395 |
> |
catch(RuntimeException ex) { // fall through |
396 |
> |
} |
397 |
> |
if (t != null) { |
398 |
> |
w.thread = t; |
399 |
> |
workers.add(w); |
400 |
> |
int nt = ++poolSize; |
401 |
> |
if (nt > largestPoolSize) |
402 |
> |
largestPoolSize = nt; |
403 |
> |
} |
404 |
|
return t; |
405 |
|
} |
406 |
|
|
543 |
|
|
544 |
|
if (state != STOP) { |
545 |
|
// If there are queued tasks but no threads, create |
546 |
< |
// replacement. |
547 |
< |
Runnable r = workQueue.poll(); |
548 |
< |
if (r != null) { |
549 |
< |
addThread(r).start(); |
540 |
< |
return; |
541 |
< |
} |
542 |
< |
|
543 |
< |
// If there are some (presumably delayed) tasks but |
544 |
< |
// none pollable, create an idle replacement to wait. |
546 |
> |
// replacement thread. We must create it initially |
547 |
> |
// idle to avoid orphaned tasks in case addThread |
548 |
> |
// fails. This also handles case of delayed tasks |
549 |
> |
// that will sometime later become runnable. |
550 |
|
if (!workQueue.isEmpty()) { |
551 |
< |
addThread(null).start(); |
551 |
> |
Thread t = addThread(null); |
552 |
> |
if (t != null) |
553 |
> |
t.start(); |
554 |
|
return; |
555 |
|
} |
556 |
|
|
1165 |
|
int extra = this.corePoolSize - corePoolSize; |
1166 |
|
this.corePoolSize = corePoolSize; |
1167 |
|
if (extra < 0) { |
1168 |
< |
Runnable r; |
1169 |
< |
while (extra++ < 0 && poolSize < corePoolSize && |
1170 |
< |
(r = workQueue.poll()) != null) |
1171 |
< |
addThread(r).start(); |
1168 |
> |
int n = workQueue.size(); |
1169 |
> |
// We have to create initially-idle threads here |
1170 |
> |
// because we otherwise have no recourse about |
1171 |
> |
// what to do with a dequeued task if addThread fails. |
1172 |
> |
while (extra++ < 0 && n-- > 0 && poolSize < corePoolSize ) { |
1173 |
> |
Thread t = addThread(null); |
1174 |
> |
if (t != null) |
1175 |
> |
t.start(); |
1176 |
> |
else |
1177 |
> |
break; |
1178 |
> |
} |
1179 |
|
} |
1180 |
|
else if (extra > 0 && poolSize > corePoolSize) { |
1181 |
|
Iterator<Worker> it = workers.iterator(); |