Last active
January 12, 2018 18:31
-
-
Save ylegall/a09a24aab92c6b9ec6f187abb6f2559d to your computer and use it in GitHub Desktop.
RejectedExecutionException example
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import java.time.Duration; | |
import java.util.concurrent.CountDownLatch; | |
import java.util.concurrent.ExecutorService; | |
import java.util.concurrent.LinkedBlockingQueue; | |
import java.util.concurrent.ThreadFactory; | |
import java.util.concurrent.ThreadPoolExecutor; | |
import java.util.concurrent.TimeUnit; | |
import java.util.concurrent.atomic.AtomicInteger; | |
/** | |
* | |
*/ | |
public class ThreadPoolTest { | |
private static final int IDLE_THREADS = 5; | |
private static final int MAX_THREADS = 5; | |
private static final int QUEUE_SIZE = 3; | |
public static void main(String[] args) throws InterruptedException { | |
final CountDownLatch latch = new CountDownLatch(MAX_THREADS); | |
final TaskFactory taskFactory = new TaskFactory(latch); | |
final ExecutorService executor = new ThreadPoolExecutor( | |
IDLE_THREADS, | |
MAX_THREADS, | |
500L, // max idle duration, but since IDLE_THREADS == maxPoolSize, thread count will not decrease | |
TimeUnit.MILLISECONDS, | |
new LinkedBlockingQueue<>(QUEUE_SIZE), | |
new DebugThreadFactory() | |
); | |
// initially send n tasks to fill pool to MAX_THREADS: | |
System.err.println("initializing core threads"); | |
for (int i = 0; i < MAX_THREADS; ++i) { | |
executor.execute(taskFactory.getTaskWithDuration(Duration.ofSeconds(1L))); | |
} | |
// wait for all initial tasks to finish so that all threads are idle | |
System.err.println("waiting for initial tasks to complete"); | |
latch.await(); | |
System.err.println("done waiting"); | |
// after the core threads have been initialized, all requests will go into the queue. | |
// therefore a burst of (queueSize + 1) requests will likely cause a RejectedExecutionException | |
System.err.println("expecting a RejectedExecutionException..."); | |
for (int i = 0; i < QUEUE_SIZE + 1; ++i) { | |
executor.execute(taskFactory.getTaskWithDuration(Duration.ofSeconds(1L))); | |
} | |
executor.shutdown(); | |
executor.awaitTermination(1L, TimeUnit.DAYS); | |
} | |
} | |
/** | |
* | |
*/ | |
class TaskFactory | |
{ | |
private final CountDownLatch latch; | |
private final AtomicInteger taskId = new AtomicInteger(1); | |
TaskFactory(final CountDownLatch latch) { | |
this.latch = latch; | |
} | |
public Runnable getTaskWithDuration(final Duration duration) { | |
return () -> { | |
final int id = taskId.getAndIncrement(); | |
try { | |
Thread.sleep(duration.toMillis()); | |
latch.countDown(); | |
System.err.println(" * finished task " + id); | |
} catch (InterruptedException e) { | |
System.err.println(e.getMessage()); | |
} | |
}; | |
} | |
} | |
/** | |
* | |
*/ | |
class DebugThreadFactory implements ThreadFactory | |
{ | |
private int threadId = 1; | |
@Override | |
public Thread newThread(final Runnable runnable) { | |
System.err.println(" * creating thread " + threadId); | |
final Thread thread = new Thread(runnable, "t-" + threadId); | |
threadId++; | |
thread.setDaemon(true); | |
return thread; | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment