34
34
import java .util .NoSuchElementException ;
35
35
import java .util .concurrent .ArrayBlockingQueue ;
36
36
import java .util .concurrent .BlockingQueue ;
37
+ import java .util .concurrent .ConcurrentLinkedQueue ;
37
38
import java .util .concurrent .ExecutionException ;
38
39
import java .util .concurrent .Executor ;
39
40
import java .util .concurrent .Future ;
40
- import java .util .concurrent .LinkedBlockingQueue ;
41
+ import java .util .concurrent .locks . LockSupport ;
41
42
import java .util .logging .Level ;
42
43
import java .util .logging .Logger ;
43
44
import javax .annotation .Nullable ;
@@ -627,10 +628,12 @@ public void onClose(Status status, Metadata trailers) {
627
628
}
628
629
}
629
630
630
- private static final class ThreadlessExecutor implements Executor {
631
+ @ SuppressWarnings ("serial" )
632
+ private static final class ThreadlessExecutor extends ConcurrentLinkedQueue <Runnable >
633
+ implements Executor {
631
634
private static final Logger log = Logger .getLogger (ThreadlessExecutor .class .getName ());
632
635
633
- private final BlockingQueue < Runnable > queue = new LinkedBlockingQueue <>() ;
636
+ private volatile Thread waiter ;
634
637
635
638
// Non private to avoid synthetic class
636
639
ThreadlessExecutor () {}
@@ -639,20 +642,33 @@ private static final class ThreadlessExecutor implements Executor {
639
642
* Waits until there is a Runnable, then executes it and all queued Runnables after it.
640
643
*/
641
644
public void waitAndDrain () throws InterruptedException {
642
- Runnable runnable = queue .take ();
643
- while (runnable != null ) {
645
+ Runnable runnable = poll ();
646
+ if (runnable == null ) {
647
+ waiter = Thread .currentThread ();
648
+ try {
649
+ while ((runnable = poll ()) == null ) {
650
+ LockSupport .park (this );
651
+ }
652
+ } finally {
653
+ waiter = null ;
654
+ }
655
+ }
656
+ do {
644
657
try {
645
658
runnable .run ();
646
659
} catch (Throwable t ) {
647
660
log .log (Level .WARNING , "Runnable threw exception" , t );
648
661
}
649
- runnable = queue .poll ();
650
- }
662
+ } while ((runnable = poll ()) != null );
651
663
}
652
664
653
665
@ Override
654
666
public void execute (Runnable runnable ) {
655
- queue .add (runnable );
667
+ add (runnable );
668
+ final Thread waitingThread = waiter ;
669
+ if (waitingThread != null ) {
670
+ LockSupport .unpark (waitingThread );
671
+ }
656
672
}
657
673
}
658
674
}
0 commit comments