Skip to content

Commit 92b50a1

Browse files
author
Jan Gaspar
committed
drain with timeout
1 parent 4b59eec commit 92b50a1

4 files changed

Lines changed: 39 additions & 27 deletions

File tree

README.md

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -71,13 +71,12 @@ boundedExecutor.execute(aTask);
7171
7272
// execute more tasks ... at most 10 will be scheduled
7373
74-
// before shutting down you can call a drain() method which blocks until all submitted task have been executed
75-
boundedExecutor.drain();
74+
// before shutting down you can call a 'drain' method which blocks until all submitted task have been executed
75+
boundedExecutor.drain(aTimeout, TimeUnit.SECONDS); // returns true if drained; false if timeout elapses
7676
77-
// newly submitted tasks will be rejected after calling drain()
77+
// newly submitted tasks will be rejected after calling 'drain'
7878
79-
underlyingExecutor.shutdown();
80-
underlyingExecutor.awaitTermination(aTimeout, TimeUnit.SECONDS);
79+
underlyingExecutor.shutdownNow(); // safe to call 'shutdownNow' if drained as there should be no active tasks
8180
```
8281
The source code of the examples can be found [here](src/test/java/com/jano7/executor/Examples.java).
8382

@@ -88,6 +87,6 @@ from multiple threads without synchronization.
8887
<dependency>
8988
<groupId>com.jano7</groupId>
9089
<artifactId>executor</artifactId>
91-
<version>1.0.3</version>
90+
<version>1.0.4</version>
9291
</dependency>
9392
```

src/main/java/com/jano7/executor/BoundedExecutor.java

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ of this software and associated documentation files (the "Software"), to deal
2626
import java.util.concurrent.Executor;
2727
import java.util.concurrent.RejectedExecutionException;
2828
import java.util.concurrent.Semaphore;
29+
import java.util.concurrent.TimeUnit;
2930

3031
public final class BoundedExecutor implements Executor {
3132

@@ -74,11 +75,11 @@ public void execute(Runnable task) {
7475
}
7576
}
7677

77-
public void drain() {
78-
synchronized (this) {
79-
semaphore.acquireUninterruptibly(maxTasks);
78+
public synchronized boolean drain(long timeout, TimeUnit unit) throws InterruptedException {
79+
if (semaphore.tryAcquire(maxTasks, timeout, unit)) {
8080
drained = true;
81+
semaphore.release(maxTasks);
8182
}
82-
semaphore.release(maxTasks);
83+
return drained;
8384
}
8485
}

src/test/java/com/jano7/executor/BoundedExecutorTest.java

Lines changed: 25 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -117,33 +117,46 @@ public void execute(Runnable command) {
117117
assertTrue(thrown);
118118
}
119119

120-
@Test(timeout = 5000)
120+
@Test(timeout = 10000)
121121
public void drain() throws InterruptedException {
122-
ExecutorService underlying = Executors.newFixedThreadPool(5);
123-
124122
for (int i = 0; i < 1000; ++i) {
123+
ExecutorService underlying = Executors.newFixedThreadPool(5);
125124
BoundedExecutor bounded = new BoundedExecutor(10, underlying);
125+
CountDownLatch latch = new CountDownLatch(1);
126126
AtomicInteger completed = new AtomicInteger(0);
127+
127128
for (int j = 0; j < 10; ++j) {
128129
bounded.execute(completed::incrementAndGet);
129130
}
130-
bounded.drain();
131-
assertEquals(10, completed.get());
131+
bounded.execute(() -> {
132+
try {
133+
latch.await();
134+
completed.incrementAndGet();
135+
} catch (InterruptedException e) {
136+
throw new RuntimeException(e);
137+
}
138+
});
139+
140+
assertFalse(bounded.drain(1, TimeUnit.MILLISECONDS));
141+
142+
latch.countDown();
143+
144+
assertTrue(bounded.drain(Long.MAX_VALUE, TimeUnit.SECONDS));
145+
assertEquals(11, completed.get());
146+
assertTrue(underlying.shutdownNow().isEmpty());
132147
}
133148

134-
underlying.shutdown();
135-
underlying.awaitTermination(Long.MAX_VALUE, TimeUnit.SECONDS);
136149
}
137150

138151
@Test(timeout = 5000, expected = RejectedExecutionException.class)
139-
public void rejectTasksAfterDrain() {
152+
public void rejectTasksAfterDrain() throws InterruptedException {
140153
ExecutorService underlying = Executors.newCachedThreadPool();
141154
BoundedExecutor bounded = new BoundedExecutor(10, underlying);
142155

143156
bounded.execute(() -> {
144157
});
145158

146-
bounded.drain();
159+
bounded.drain(Long.MAX_VALUE, TimeUnit.SECONDS);
147160
try {
148161
bounded.execute(() -> {
149162
});
@@ -153,15 +166,15 @@ public void rejectTasksAfterDrain() {
153166
}
154167

155168
@Test(timeout = 5000)
156-
public void callDrainMultipleTime() {
169+
public void callDrainMultipleTime() throws InterruptedException {
157170
ExecutorService underlying = Executors.newCachedThreadPool();
158171
BoundedExecutor bounded = new BoundedExecutor(10, underlying);
159172

160173
bounded.execute(() -> {
161174
});
162175

163-
bounded.drain();
164-
bounded.drain();
176+
bounded.drain(Long.MAX_VALUE, TimeUnit.SECONDS);
177+
bounded.drain(Long.MAX_VALUE, TimeUnit.SECONDS);
165178

166179
underlying.shutdownNow();
167180
}

src/test/java/com/jano7/executor/Examples.java

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -76,13 +76,12 @@ public static void boundedExecutorExample() throws InterruptedException {
7676

7777
// execute more tasks ... at most 10 will be scheduled
7878

79-
// before shutting down you can call a drain() method which blocks until all submitted task have been executed
80-
boundedExecutor.drain();
79+
// before shutting down you can call a 'drain' method which blocks until all submitted task have been executed
80+
boundedExecutor.drain(aTimeout, TimeUnit.SECONDS); // returns true if drained; false if timeout elapses
8181

82-
// newly submitted tasks will be rejected after calling drain()
82+
// newly submitted tasks will be rejected after calling 'drain'
8383

84-
underlyingExecutor.shutdown();
85-
underlyingExecutor.awaitTermination(aTimeout, TimeUnit.SECONDS);
84+
underlyingExecutor.shutdownNow(); // safe to call 'shutdownNow' if drained as there should be no active tasks
8685
}
8786

8887
public static void main(String[] args) throws InterruptedException {

0 commit comments

Comments
 (0)