533 |
|
|
534 |
|
/** |
535 |
|
* Class Worker mainly maintains interrupt control state for |
536 |
< |
* threads running tasks, along with other minor bookkeeping. This |
537 |
< |
* class opportunistically extends ReentrantLock to simplify |
538 |
< |
* acquiring and releasing a lock surrounding each task execution. |
539 |
< |
* This protects against interrupts that are intended to wake up a |
540 |
< |
* worker thread waiting for a task from instead interrupting a |
541 |
< |
* task being run. |
542 |
< |
*/ |
543 |
< |
private final class Worker extends ReentrantLock implements Runnable { |
536 |
> |
* threads running tasks, along with other minor bookkeeping. |
537 |
> |
* This class opportunistically extends AbstractQueuedSynchronizer |
538 |
> |
* to simplify acquiring and releasing a lock surrounding each |
539 |
> |
* task execution. This protects against interrupts that are |
540 |
> |
* intended to wake up a worker thread waiting for a task from |
541 |
> |
* instead interrupting a task being run. We implement a simple |
542 |
> |
* non-reentrant mutual exclusion lock rather than use ReentrantLock |
543 |
> |
* because we do not want worker tasks to be able to reacquire the |
544 |
> |
* lock when they invoke pool control methods like setCorePoolSize. |
545 |
> |
*/ |
546 |
> |
private final class Worker |
547 |
> |
extends AbstractQueuedSynchronizer |
548 |
> |
implements Runnable |
549 |
> |
{ |
550 |
|
/** |
551 |
|
* This class will never be serialized, but we provide a |
552 |
|
* serialVersionUID to suppress a javac warning. |
573 |
|
public void run() { |
574 |
|
runWorker(this); |
575 |
|
} |
576 |
+ |
|
577 |
+ |
// Lock methods |
578 |
+ |
// |
579 |
+ |
// The value 0 represents the unlocked state. |
580 |
+ |
// The value 1 represents the locked state. |
581 |
+ |
|
582 |
+ |
protected boolean isHeldExclusively() { |
583 |
+ |
return getState() == 1; |
584 |
+ |
} |
585 |
+ |
|
586 |
+ |
protected boolean tryAcquire(int unused) { |
587 |
+ |
if (compareAndSetState(0, 1)) { |
588 |
+ |
setExclusiveOwnerThread(Thread.currentThread()); |
589 |
+ |
return true; |
590 |
+ |
} |
591 |
+ |
return false; |
592 |
+ |
} |
593 |
+ |
|
594 |
+ |
protected boolean tryRelease(int unused) { |
595 |
+ |
setExclusiveOwnerThread(null); |
596 |
+ |
setState(0); |
597 |
+ |
return true; |
598 |
+ |
} |
599 |
+ |
|
600 |
+ |
public void lock() { acquire(1); } |
601 |
+ |
public boolean tryLock() { return tryAcquire(1); } |
602 |
+ |
public void unlock() { release(1); } |
603 |
+ |
public boolean isLocked() { return isHeldExclusively(); } |
604 |
|
} |
605 |
|
|
606 |
|
/* |
730 |
|
* waiting for a straggler task to finish. |
731 |
|
*/ |
732 |
|
private void interruptIdleWorkers(boolean onlyOne) { |
733 |
< |
final ReentrantLock mainLock = this.mainLock; |
733 |
> |
final ReentrantLock mainLock = this.mainLock; |
734 |
|
mainLock.lock(); |
735 |
|
try { |
736 |
|
for (Worker w : workers) { |
737 |
|
Thread t = w.thread; |
738 |
< |
if (!t.isInterrupted() && w.tryLock()) { |
738 |
> |
if (!t.isInterrupted() && w.tryLock()) { |
739 |
|
try { |
740 |
|
t.interrupt(); |
741 |
|
} catch (SecurityException ignore) { |