905 |
|
*/ |
906 |
|
|
907 |
|
final ReentrantLock runLock = this.runLock; |
908 |
< |
Runnable task = firstTask; |
909 |
< |
firstTask = null; |
910 |
< |
try { |
911 |
< |
while (task != null || (task = getTask()) != null) { |
908 |
> |
boolean completedAbruptly = true; |
909 |
> |
try { |
910 |
> |
Runnable task = (firstTask != null) ? firstTask : getTask(); |
911 |
> |
firstTask = null; |
912 |
> |
for (; task != null; task = getTask()) { |
913 |
|
runLock.lock(); |
914 |
|
try { |
915 |
+ |
/* |
916 |
+ |
* Ensure that unless pool is stopping, this thread |
917 |
+ |
* does not have its interrupt set. This requires a |
918 |
+ |
* double-check of state in case the interrupt was |
919 |
+ |
* cleared concurrently with a shutdownNow -- if so, |
920 |
+ |
* the interrupt is re-enabled. |
921 |
+ |
*/ |
922 |
|
if (runState < STOP && |
923 |
|
Thread.interrupted() && |
924 |
|
runState >= STOP) |
925 |
|
thread.interrupt(); |
926 |
|
|
927 |
|
beforeExecute(thread, task); |
928 |
< |
Throwable thrown = null; |
928 |
> |
|
929 |
> |
Throwable thrown = null; |
930 |
|
try { |
931 |
|
task.run(); |
932 |
|
} catch (RuntimeException x) { |
939 |
|
afterExecute(task, thrown); |
940 |
|
} |
941 |
|
} finally { |
933 |
– |
task = null; |
942 |
|
++completedTasks; |
943 |
|
runLock.unlock(); |
944 |
|
} |
945 |
|
} |
946 |
+ |
completedAbruptly = false; |
947 |
|
} finally { |
948 |
< |
workerDone(this); |
948 |
> |
workerDone(this, completedAbruptly); |
949 |
|
} |
950 |
|
} |
951 |
|
} |
1041 |
|
* 2. Generate a replacement thread if there are any queued tasks |
1042 |
|
* and the pool is not shutting down. |
1043 |
|
* @param w the worker |
1044 |
+ |
* @param completedAbruptly whether w died due to a task throwing |
1045 |
|
*/ |
1046 |
< |
void workerDone(Worker w) { |
1046 |
> |
void workerDone(Worker w, boolean completedAbruptly) { |
1047 |
|
Thread replacement = null; |
1048 |
|
final ReentrantLock mainLock = this.mainLock; |
1049 |
|
mainLock.lock(); |
1051 |
|
completedTaskCount += w.completedTasks; |
1052 |
|
workers.remove(w); |
1053 |
|
int n = --poolSize; |
1054 |
< |
if (runState < STOP && !workQueue.isEmpty()) |
1054 |
> |
if (runState < STOP && |
1055 |
> |
(completedAbruptly || !workQueue.isEmpty())) |
1056 |
|
replacement = addThread(null); |
1057 |
|
else if (n == 0) |
1058 |
|
tryTerminate(); |