I started reading more about ThreadPoolExecutor from Java Doc as I am using it in one of my project. So Can anyone explain me what does this line means actually?- I know what does each parameter stands for, but I wanted to understand it in more general/lay-man way from some of the experts here.
ExecutorService service = new ThreadPoolExecutor(10, 10, 1000L,
TimeUnit.MILLISECONDS, new ArrayBlockingQueue<Runnable>(10, true), new
ThreadPoolExecutor.CallerRunsPolicy());
Updated:-
Problem Statement is:-
Each thread uses unique ID between 1 and 1000 and program has to run for 60 minutes or more, So in that 60 minutes it is possible that all the ID's will get finished so I need to reuse those ID's again. So this is the below program I wrote by using above executor.
class IdPool {
private final LinkedList<Integer> availableExistingIds = new LinkedList<Integer>();
public IdPool() {
for (int i = 1; i <= 1000; i++) {
availableExistingIds.add(i);
}
}
public synchronized Integer getExistingId() {
return availableExistingIds.removeFirst();
}
public synchronized void releaseExistingId(Integer id) {
availableExistingIds.add(id);
}
}
class ThreadNewTask implements Runnable {
private IdPool idPool;
public ThreadNewTask(IdPool idPool) {
this.idPool = idPool;
}
public void run() {
Integer id = idPool.getExistingId();
someMethod(id);
idPool.releaseExistingId(id);
}
// This method needs to be synchronized or not?
private synchronized void someMethod(Integer id) {
System.out.println("Task: " +id);
// and do other calcuations whatever you need to do in your program
}
}
public class TestingPool {
public static void main(String[] args) throws InterruptedException {
int size = 10;
int durationOfRun = 60;
IdPool idPool = new IdPool();
// create thread pool with given size
ExecutorService service = new ThreadPoolExecutor(size, size, 500L, TimeUnit.MILLISECONDS, new ArrayBlockingQueue<Runnable>(size), new ThreadPoolExecutor.CallerRunsPolicy());
// queue some tasks
long startTime = System.currentTimeMillis();
long endTime = startTime + (durationOfRun * 60 * 1000L);
// Running it for 60 minutes
while(System.currentTimeMillis() <= endTime) {
service.submit(new ThreadNewTask(idPool));
}
// wait for termination
service.shutdown();
service.awaitTermination(Long.MAX_VALUE, TimeUnit.DAYS);
}
}
My Questions is:- This code is right as far as the Performance is considered or not? And what else I can make it here to make it more accurate? Any help will be appreciated.
[First, i apologize, this is a response to a previous answer, but i wanted formatting].
Except in reality, you DON'T block when an item is submitted to a ThreadPoolExecutor with a full queue. The reason for this is that ThreadPoolExecutor calls the BlockingQueue.offer(T item) method which by definition is a non-blocking method. It either adds the item and returns true, or does not add (when full) and returns false. The ThreadPoolExecutor then calls the registered RejectedExecutionHandler to deal with this situation.
From the javadoc:
Executes the given task sometime in the future. The task may execute
in a new thread or in an existing pooled thread. If the task cannot be
submitted for execution, either because this executor has been
shutdown or because its capacity has been reached, the task is handled
by the current RejectedExecutionHandler.
By default, the ThreadPoolExecutor.AbortPolicy() is used which throws a RejectedExecutionException from the "submit" or "execute" method of the ThreadPoolExecutor.
try {
executorService.execute(new Runnable() { ... });
}
catch (RejectedExecutionException e) {
// the queue is full, and you're using the AbortPolicy as the
// RejectedExecutionHandler
}
However, you can use other handlers to do something different, such as ignore the error (DiscardPolicy), or run it in the thread which called the "execute" or "submit" method (CallerRunsPolicy). This example lets whichever thread calls the "submit" or "execute" method run the requested task when the queue is full. (this means at any given time, you could 1 additional thing running on top of what's in the pool itself):
ExecutorService service = new ThreadPoolExecutor(..., new ThreadPoolExecutor.CallerRunsPolicy());
If you want to block and wait, you could implement your own RejectedExecutionHandler which would block until there's a slot available on the queue (this is a rough estimate, i have not compiled or run this, but you should get the idea):
public class BlockUntilAvailableSlot implements RejectedExecutionHandler {
public void rejectedExecution(Runnable r, ThreadPoolExecutor e) {
if (e.isTerminated() || e.isShutdown()) {
return;
}
boolean submitted = false;
while (! submitted) {
if (Thread.currentThread().isInterrupted()) {
// be a good citizen and do something nice if we were interrupted
// anywhere other than during the sleep method.
}
try {
e.execute(r);
submitted = true;
}
catch (RejectedExceptionException e) {
try {
// Sleep for a little bit, and try again.
Thread.sleep(100L);
}
catch (InterruptedException e) {
; // do you care if someone called Thread.interrupt?
// if so, do something nice here, and maybe just silently return.
}
}
}
}
}
It's creating an ExecutorService which handles the execution of a pool of threads. Both the initial and maximum number of threads in the pool is 10 in this case. When a thread in the pool becomes idle for 1 second (1000ms) it will kill it (the idle timer), however because the max and core number of threads is the same, this will never happen (it always keeps 10 threads around and will never run more than 10 threads).
It uses an ArrayBlockingQueue to manage the execution requests with 10 slots, so when the queue is full (after 10 threads have been enqueued), it will block the caller.
If thread is rejected (which in this case would be due to the service shutting down, since threads will be queued or you will be blocked when queuing a thread if the queue is full), then the offered Runnable will be executed on the caller's thread.
Consider semaphores. These are meant for the same purpose. Please check below for the code using semaphore. Not sure if this is what you want. But this will block if there are no more permits to acquire. Also is ID important to you?
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Semaphore;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
class ThreadNewTask implements Runnable {
private Semaphore idPool;
public ThreadNewTask(Semaphore idPool) {
this.idPool = idPool;
}
public void run() {
// Integer id = idPool.getExistingId();
try {
idPool.acquire();
someMethod(0);
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
idPool.release();
}
// idPool.releaseExistingId(id);
}
// This method needs to be synchronized or not?
private void someMethod(Integer id) {
System.out.println("Task: " + id);
// and do other calcuations whatever you need to do in your program
}
}
public class TestingPool {
public static void main(String[] args) throws InterruptedException {
int size = 10;
int durationOfRun = 60;
Semaphore idPool = new Semaphore(100);
// IdPool idPool = new IdPool();
// create thread pool with given size
ExecutorService service = new ThreadPoolExecutor(size, size, 500L,
TimeUnit.MILLISECONDS, new ArrayBlockingQueue<Runnable>(size),
new ThreadPoolExecutor.CallerRunsPolicy());
// queue some tasks
long startTime = System.currentTimeMillis();
long endTime = startTime + (durationOfRun * 60 * 1000L);
// Running it for 60 minutes
while (System.currentTimeMillis() <= endTime) {
service.submit(new ThreadNewTask(idPool));
}
// wait for termination
service.shutdown();
service.awaitTermination(Long.MAX_VALUE, TimeUnit.DAYS);
}
}
Another solution is to hack underlying queue to replace offer with offer with large timeout (up to 292 years, can be considered infinite).
// helper method
private static boolean interruptibleInfiniteOffer(BlockingQueue<Runnable> q, Runnable r) {
try {
return q.offer(r, Long.MAX_VALUE, TimeUnit.NANOSECONDS); // infinite == ~292 years
} catch (InterruptedException e) {
return false;
}
}
// fixed size pool with blocking (instead of rejecting) if bounded queue is full
public static ThreadPoolExecutor getFixedSizePoolWithLimitedWaitingQueue(int nThreads, int maxItemsInTheQueue) {
BlockingQueue<Runnable> queue = maxItemsInTheQueue == 0
? new SynchronousQueue<>() { public boolean offer(Runnable r) { return interruptibleInfiniteOffer(this, r);} }
: new ArrayBlockingQueue<>(maxItemsInTheQueue) { public boolean offer(Runnable r) { return interruptibleInfiniteOffer(this, r);} };
return new ThreadPoolExecutor(nThreads, nThreads, 0, TimeUnit.MILLISECONDS, queue);
}
Related
This question already has answers here:
ThreadPoolExecutor Block When its Queue Is Full?
(10 answers)
Closed 1 year ago.
I am trying to code a solution in which a single thread produces I/O-intensive tasks that can be performed in parallel. Each task have significant in-memory data. So I want to be able limit the number of tasks that are pending at a moment.
If I create ThreadPoolExecutor like this:
ThreadPoolExecutor executor = new ThreadPoolExecutor(numWorkerThreads, numWorkerThreads,
0L, TimeUnit.MILLISECONDS,
new LinkedBlockingQueue<Runnable>(maxQueue));
Then the executor.submit(callable) throws RejectedExecutionException when the queue fills up and all the threads are already busy.
What can I do to make executor.submit(callable) block when the queue is full and all threads are busy?
EDIT:
I tried this:
executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());
And it somewhat achieves the effect that I want achieved but in an inelegant way (basically rejected threads are run in the calling thread, so this blocks the calling thread from submitting more).
EDIT: (5 years after asking the question)
To anyone reading this question and its answers, please don't take the accepted answer as one correct solution. Please read through all answers and comments.
I have done this same thing. The trick is to create a BlockingQueue where the offer() method is really a put(). (you can use whatever base BlockingQueue impl you want).
public class LimitedQueue<E> extends LinkedBlockingQueue<E>
{
public LimitedQueue(int maxSize)
{
super(maxSize);
}
#Override
public boolean offer(E e)
{
// turn offer() and add() into a blocking calls (unless interrupted)
try {
put(e);
return true;
} catch(InterruptedException ie) {
Thread.currentThread().interrupt();
}
return false;
}
}
Note that this only works for thread pool where corePoolSize==maxPoolSize so be careful there (see comments).
The currently accepted answer has a potentially significant problem - it changes the behavior of ThreadPoolExecutor.execute such that if you have a corePoolSize < maxPoolSize, the ThreadPoolExecutor logic will never add additional workers beyond the core.
From ThreadPoolExecutor.execute(Runnable):
if (isRunning(c) && workQueue.offer(command)) {
int recheck = ctl.get();
if (! isRunning(recheck) && remove(command))
reject(command);
else if (workerCountOf(recheck) == 0)
addWorker(null, false);
}
else if (!addWorker(command, false))
reject(command);
Specifically, that last 'else' block willl never be hit.
A better alternative is to do something similar to what OP is already doing - use a RejectedExecutionHandler to do the same put logic:
public void rejectedExecution(Runnable r, ThreadPoolExecutor executor) {
try {
if (!executor.isShutdown()) {
executor.getQueue().put(r);
}
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
throw new RejectedExecutionException("Executor was interrupted while the task was waiting to put on work queue", e);
}
}
There are some things to watch out for with this approach, as pointed out in the comments (referring to this answer):
If corePoolSize==0, then there is a race condition where all threads in the pool may die before the task is visible
Using an implementation that wraps the queue tasks (not applicable to ThreadPoolExecutor) will result in issues unless the handler also wraps it the same way.
Keeping those gotchas in mind, this solution will work for most typical ThreadPoolExecutors, and will properly handle the case where corePoolSize < maxPoolSize.
Here is how I solved this on my end:
(note: this solution does block the thread that submits the Callable, so it prevents RejectedExecutionException from being thrown )
public class BoundedExecutor extends ThreadPoolExecutor{
private final Semaphore semaphore;
public BoundedExecutor(int bound) {
super(bound, Integer.MAX_VALUE, 60L, TimeUnit.SECONDS, new SynchronousQueue<Runnable>());
semaphore = new Semaphore(bound);
}
/**Submits task to execution pool, but blocks while number of running threads
* has reached the bound limit
*/
public <T> Future<T> submitButBlockIfFull(final Callable<T> task) throws InterruptedException{
semaphore.acquire();
return submit(task);
}
#Override
protected void afterExecute(Runnable r, Throwable t) {
super.afterExecute(r, t);
semaphore.release();
}
}
How about using the CallerBlocksPolicy class if you are using spring-integration?
This class implements the RejectedExecutionHandler interface, which is a handler for tasks that cannot be executed by a ThreadPoolExecutor.
You can use this policy like this.
executor.setRejectedExecutionHandler(new CallerBlocksPolicy());
The main difference between CallerBlocksPolicy and CallerRunsPolicy is whether it blocks or runs the task in the caller thread.
Please refer to this code.
I know this is an old question but had a similar issue that creating new tasks was very fast and if there were too many an OutOfMemoryError occur because existing task were not completed fast enough.
In my case Callables are submitted and I need the result hence I need to store all the Futures returned by executor.submit(). My solution was to put the Futures into a BlockingQueue with a maximum size. Once that queue is full, no more tasks are generated until some are completed (elements removed from queue). In pseudo-code:
final ExecutorService executor = Executors.newFixedThreadPool(numWorkerThreads);
final LinkedBlockingQueue<Future> futures = new LinkedBlockingQueue<>(maxQueueSize);
try {
Thread taskGenerator = new Thread() {
#Override
public void run() {
while (reader.hasNext) {
Callable task = generateTask(reader.next());
Future future = executor.submit(task);
try {
// if queue is full blocks until a task
// is completed and hence no future tasks are submitted.
futures.put(future);
} catch (InterruptedException ex) {
Thread.currentThread().interrupt();
}
}
executor.shutdown();
}
}
taskGenerator.start();
// read from queue as long as task are being generated
// or while Queue has elements in it
while (taskGenerator.isAlive()
|| !futures.isEmpty()) {
Future future = futures.take();
// do something
}
} catch (InterruptedException ex) {
Thread.currentThread().interrupt();
} catch (ExecutionException ex) {
throw new MyException(ex);
} finally {
executor.shutdownNow();
}
I had the similar problem and I implemented that by using beforeExecute/afterExecute hooks from ThreadPoolExecutor:
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.ReentrantLock;
/**
* Blocks current task execution if there is not enough resources for it.
* Maximum task count usage controlled by maxTaskCount property.
*/
public class BlockingThreadPoolExecutor extends ThreadPoolExecutor {
private final ReentrantLock taskLock = new ReentrantLock();
private final Condition unpaused = taskLock.newCondition();
private final int maxTaskCount;
private volatile int currentTaskCount;
public BlockingThreadPoolExecutor(int corePoolSize, int maximumPoolSize,
long keepAliveTime, TimeUnit unit,
BlockingQueue<Runnable> workQueue, int maxTaskCount) {
super(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue);
this.maxTaskCount = maxTaskCount;
}
/**
* Executes task if there is enough system resources for it. Otherwise
* waits.
*/
#Override
protected void beforeExecute(Thread t, Runnable r) {
super.beforeExecute(t, r);
taskLock.lock();
try {
// Spin while we will not have enough capacity for this job
while (maxTaskCount < currentTaskCount) {
try {
unpaused.await();
} catch (InterruptedException e) {
t.interrupt();
}
}
currentTaskCount++;
} finally {
taskLock.unlock();
}
}
/**
* Signalling that one more task is welcome
*/
#Override
protected void afterExecute(Runnable r, Throwable t) {
super.afterExecute(r, t);
taskLock.lock();
try {
currentTaskCount--;
unpaused.signalAll();
} finally {
taskLock.unlock();
}
}
}
This should be good enough for you. Btw, original implementation was task size based because one task could be larger 100 time than another and submitting two huge tasks was killing the box, but running one big and plenty of small was Okay. If your I/O-intensive tasks are roughly the same size you could use this class, otherwise just let me know and I'll post size based implementation.
P.S. You would want to check ThreadPoolExecutor javadoc. It's really nice user guide from Doug Lea about how it could be easily customized.
I have implemented a solution following the decorator pattern and using a semaphore to control the number of executed tasks. You can use it with any Executor and:
Specify the maximum of ongoing tasks
Specify the maximum timeout to wait for a task execution permit (if the timeout passes and no permit is acquired, a RejectedExecutionException is thrown)
import static java.util.concurrent.TimeUnit.MILLISECONDS;
import java.time.Duration;
import java.util.Objects;
import java.util.concurrent.Executor;
import java.util.concurrent.RejectedExecutionException;
import java.util.concurrent.Semaphore;
import javax.annotation.Nonnull;
public class BlockingOnFullQueueExecutorDecorator implements Executor {
private static final class PermitReleasingDecorator implements Runnable {
#Nonnull
private final Runnable delegate;
#Nonnull
private final Semaphore semaphore;
private PermitReleasingDecorator(#Nonnull final Runnable task, #Nonnull final Semaphore semaphoreToRelease) {
this.delegate = task;
this.semaphore = semaphoreToRelease;
}
#Override
public void run() {
try {
this.delegate.run();
}
finally {
// however execution goes, release permit for next task
this.semaphore.release();
}
}
#Override
public final String toString() {
return String.format("%s[delegate='%s']", getClass().getSimpleName(), this.delegate);
}
}
#Nonnull
private final Semaphore taskLimit;
#Nonnull
private final Duration timeout;
#Nonnull
private final Executor delegate;
public BlockingOnFullQueueExecutorDecorator(#Nonnull final Executor executor, final int maximumTaskNumber, #Nonnull final Duration maximumTimeout) {
this.delegate = Objects.requireNonNull(executor, "'executor' must not be null");
if (maximumTaskNumber < 1) {
throw new IllegalArgumentException(String.format("At least one task must be permitted, not '%d'", maximumTaskNumber));
}
this.timeout = Objects.requireNonNull(maximumTimeout, "'maximumTimeout' must not be null");
if (this.timeout.isNegative()) {
throw new IllegalArgumentException("'maximumTimeout' must not be negative");
}
this.taskLimit = new Semaphore(maximumTaskNumber);
}
#Override
public final void execute(final Runnable command) {
Objects.requireNonNull(command, "'command' must not be null");
try {
// attempt to acquire permit for task execution
if (!this.taskLimit.tryAcquire(this.timeout.toMillis(), MILLISECONDS)) {
throw new RejectedExecutionException(String.format("Executor '%s' busy", this.delegate));
}
}
catch (final InterruptedException e) {
// restore interrupt status
Thread.currentThread().interrupt();
throw new IllegalStateException(e);
}
this.delegate.execute(new PermitReleasingDecorator(command, this.taskLimit));
}
#Override
public final String toString() {
return String.format("%s[availablePermits='%s',timeout='%s',delegate='%s']", getClass().getSimpleName(), this.taskLimit.availablePermits(),
this.timeout, this.delegate);
}
}
I think it is as simple as using a ArrayBlockingQueue instead of a a LinkedBlockingQueue.
Ignore me... that's totally wrong. ThreadPoolExecutor calls Queue#offer not put which would have the effect you require.
You could extend ThreadPoolExecutor and provide an implementation of execute(Runnable) that calls put in place of offer.
That doesn't seem like a completely satisfactory answer I'm afraid.
I am trying to manipulate this program to print ":---)))))" repeatedly.
I understand that a semaphore is a way of controlling threads, and acquire essentially acquires a permit (reads) and release returns a permit back to the semaphore. (writes)
I've tried manipulating the number of permits when initializing the semaphores, but I am not understanding how to sync them together because I can't figure out how exactly the semaphores operate with how they acquire and release.
I am looking for a helpful explanation that pertains to Java in the context of only using semaphores, acquire and release and how they work together to properly put the threads "in sync"
import java.lang.Thread;
import java.util.concurrent.*;
public class ThreadSync {
private static boolean runFlag = true;
private static Semaphore canPrintC = new Semaphore(1);
private static Semaphore canPrintD = new Semaphore(0);
private static Semaphore canPrintP = new Semaphore(0);
public static void main(String [] args) {
// Create and start each runnable
Runnable task1 = new TaskPrintC();
Runnable task2 = new TaskPrintD();
Runnable task3 = new TaskPrintP();
Thread thread1 = new Thread(task1);
Thread thread2 = new Thread(task2);
Thread thread3 = new Thread(task3);
thread1.start();
thread2.start();
thread3.start();
// Let them run for 500 ms
try {
Thread.sleep(500);
}
catch (InterruptedException e) {
e.printStackTrace();
}
runFlag = false;
thread3.interrupt();
thread2.interrupt();
thread1.interrupt();
}
public static class TaskPrintC implements Runnable {
public void run() {
while (runFlag) {
try {
canPrintC.acquire();
}
catch (InterruptedException ex) {
ex.printStackTrace();
}
System.out.printf("%s", ":");
canPrintD.release();
}
}
}
public static class TaskPrintD implements Runnable {
public void run() {
while (runFlag) {
try {
canPrintD.acquire();
}
catch (InterruptedException ex) {
ex.printStackTrace();
}
System.out.printf("%s", "-");
canPrintP.release();
}
}
}
public static class TaskPrintP implements Runnable {
public void run() {
while (runFlag) {
try {
canPrintP.acquire();
}
catch (InterruptedException ex) {
ex.printStackTrace();
}
System.out.printf("%s", ")");
canPrintC.release();
}
}
}
}
Threads execute tasks and semaphores can help you to let tasks (or runnable objects) know each other's state (e.g. task A waits for input from task B and task B can signal task A that input is available). The difference between a task and a thread is important.
To stress this point, I have taken your example and made one runnable class that performs the task of printing a character a number of times (configured via variables in the constructor). To mimic the serialized behavior (tasks run after each other), the runnable is also aware of the next runnable that should perform the print task.
To complete the example I also ensured that the thread that is executing the main-method is aware of when the tasks have completed, so that the program stops at the proper time. A CountDownLatch is used in this case (a CountDownLatch is a very simple variation of a Semaphore).
The example below might be a bit hard to understand, but it shows some good practices (re-use code, using a stop-flag instead of interrupt, use an executor to run tasks, cleanup and stop tasks in case of error). It also shows how Semaphores can orchestrate the execution of tasks.
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Semaphore;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicInteger;
public class ChainedSemaphoreTasks {
// amount of times chained tasks are executed.
static int MAX_CHAINED_LOOPS = 3;
// helper to let main-thread know when chained loops have been executed.
final static CountDownLatch MAX_LOOPS_REACHED = new CountDownLatch(1);
public static void main(String[] args) {
String printChars = ":-)";
int[] repeatChars = { 1, 3, 5};
List<ChainedTask> tasks = buildTasks(printChars, repeatChars);
ExecutorService executor = Executors.newCachedThreadPool();
for (ChainedTask task : tasks) {
executor.execute(task);
}
try {
// Trigger first task to start running.
tasks.get(0).triggerPrintTask();
// wait for loop to complete, but not too long.
if (!MAX_LOOPS_REACHED.await(5000L, TimeUnit.MILLISECONDS)) {
throw new RuntimeException("Chained tasks loop did not complete within timeout.");
}
long waitStart = System.currentTimeMillis();
executor.shutdown();
if (executor.awaitTermination(1000L, TimeUnit.MILLISECONDS)) {
System.out.println("All tasks stopped within " + (System.currentTimeMillis() - waitStart) + " ms.");
} else {
throw new RuntimeException("Not all chained tasks stopped within timeout.");
}
} catch (Exception e) {
e.printStackTrace();
// cleanup
try {
tasks.get(0).stop();
} catch (Exception e2) {
e2.printStackTrace();
}
executor.shutdownNow();
}
}
static List<ChainedTask> buildTasks(String printChars, int[] repeatChars) {
List<ChainedTask> tasks = new ArrayList<ChainedTask>();
int maxTasks = printChars.length();
if (maxTasks != repeatChars.length) {
throw new IllegalArgumentException("Amount of repeats per pritn character must match amount of characters.");
}
for (int i = 0; i < maxTasks; i++) {
ChainedTask task = new ChainedTask(printChars.charAt(i), repeatChars[i]);
tasks.add(task);
if (i > 0) {
tasks.get(i - 1).setNextTask(task);
}
}
// make last task trigger first task - creates an endless loop.
tasks.get(maxTasks - 1).setNextTask(tasks.get(0));
tasks.get(maxTasks - 1).setLastTask(true);
return tasks;
}
static AtomicInteger chainedLoopsCount = new AtomicInteger();
static class ChainedTask implements Runnable {
// Semaphore to trigger execution
Semaphore performTask = new Semaphore(0);
// If stop is true, task must finish.
// stop must be volatile to ensure updated value is always visible.
volatile boolean stop = false;
// The last task is responsible for stopping execution
boolean lastTask;
// The next task to run after this task.
ChainedTask nextTask;
char printChar;
int repeatAmount;
ChainedTask(char printChar, int repeatAmount) {
this.printChar = printChar;
this.repeatAmount = repeatAmount;
System.out.println("Created " + printChar + " / " + repeatAmount);
}
void triggerPrintTask() {
performTask.release(repeatAmount);
}
void stop() {
// first indicate to stop
stop = true;
// then release a permit to pickup the stop sign.
performTask.release();
// also stop next task, unless this is the last task
if (!isLastTask()) {
getNextTask().stop();
}
}
#Override
public void run() {
try {
while (!stop) {
runTask();
}
} catch (Exception e) {
e.printStackTrace();
}
System.out.println("Stopped " + printChar + " / " + repeatAmount);
}
void runTask() throws Exception {
// wait for our turn
performTask.acquire();
// must check 'stop' after getting permit, see the stop-method:
// first stop is set to true and then a permit is released.
if (stop) {
return;
}
// print text for loop-amount
do {
System.out.print(printChar);
} while (performTask.tryAcquire());
if (isLastTask()) {
System.out.println();
// check if we should stop
if (chainedLoopsCount.incrementAndGet() >= MAX_CHAINED_LOOPS) {
// since this is the last task, the next task is the first task.
// stopping the first task will call the stop-method on all tasks, including this one.
getNextTask().stop();
// signal main-thread we are done.
MAX_LOOPS_REACHED.countDown();
}
// Sleep for a long time to test what happens when last task hangs.
// Should trigger the "cleanup" code in the main method.
// Thread.sleep(10000);
}
// trigger next chained task to run
// this has no effect if next chained task was stopped
getNextTask().triggerPrintTask();
}
void setNextTask(ChainedTask nextTask) {
this.nextTask = nextTask;
}
ChainedTask getNextTask() {
return nextTask;
}
void setLastTask(boolean lastTask) {
this.lastTask = lastTask;
}
boolean isLastTask() {
return lastTask;
}
}
}
Semaphore – to solve Producer/Consumer problem
A high level explanation of semaphore.
A semaphore contains a count indicating whether a resource is locked or available. Semaphore is a signaling mechanism (“I am done, you can carry on.”). The resource itself may not be thread safe.
Producer
semObject.Post(); // Send the signal
Increase the semaphore count by 1. If a thread is waiting on the
specified semaphore, it is awakened.[1]
Consumer
semObject.Wait(); // Wait for the signal
When the semaphore count is zero, the thread calling this function
will wait for the semaphore. When the semaphore count is nonzero, the
count will be decremented by 1 and the thread calling this function
will continue.[1]
Reference
[1] Massa, Anthony J., Embedded software development with eCos, Pearson Education, Inc., 2002
I am trying to make an ExecutorService implementation that can be provided with a timeout or interrupt for each thread.
In my below example, suppose I am spawning 2 threads (in actual scenario, this number will be high), then I need to make sure each thread should be running for 10 minutes.
That means, Thread1 will run for 10 minutes and Thread2 will run for 10 minutes as well. If 10 minutes is over then I need to interrup the thread or timeout.
Below is the code I have so far and I am not able to understand how should I add this interrupt or timeout functionality here in such a clean way so that if I am making this no of threads parameter configurable in my code then it should work properly there as well.
public static void main(String[] args) {
final int noOfThreads = 2;
final long exp_time_millis = 600000; //10 minutes
//create thread pool with given size
ExecutorService service = Executors.newFixedThreadPool(noOfThreads);
for (int i = 0, i< noOfThreads; i++) {
service.submit(new ThreadTask());
}
}
class ThreadTask implements Runnable {
#Override
public void run() {
while(true) {
System.out.println("Thread running...");
try {
/* make a select sql to the database
* and measure how much time it is taking in
* returning the response
*/
} catch (InterruptedException e) {
}
}
}
}
Any suggestions will be of great help.
I have already seen few articles on the SO but I was not able to find anything which matches my scenario and I can implement that easily.
Updated Code:-
I am trying the below code but it gives me error on the catch block in the run method. Not sure if I am doing anything wrong. Can anyone help me?
public class ThreadTimeout {
public static void main(String[] args) {
final int noOfThreads = 2;
//create thread pool with given size
ExecutorService service = Executors.newFixedThreadPool(noOfThreads);
ScheduledExecutorService scheduleService = Executors.newScheduledThreadPool(noOfThreads);
for (int i = 0; i< noOfThreads; i++) {
final Future future = service.submit(new ThreadTask());
scheduleService.schedule(new Runnable(){
public void run(){
future.cancel(true);
}
}, 10, TimeUnit.MINUTES);
}
}
}
class ThreadTask implements Runnable {
#Override
public void run() {
//make a database connection
while (true) {
System.out.println("Thread running...");
try {
/*
* make a select sql to the database and measure
* how much time it is taking in returning the
* response
*/
} catch (InterruptedException e) {
}
}
}
}
I would recommend using a second ScheduledExecutorService. You can submit the Future returned from your original submissions to the ScheduledExecutorService to cancel.
ScheduledExecutorService scheduleService = Executors.newScheduledThreadPool(n);
for (int i = 0, i< noOfThreads; i++) {
final Future future = service.submit(new ThreadTask());
scheduleService.schedule(new Runnable(){
public void run(){
future.cancel(true);
}
}, 10, TimeUnits.MINUTES);
}
Now the ThreadTask needs to respond to interruption or else this will not help.
What I would recommend is to use the ExecutorService.awaitTermination(...); method and then the ExecutorService.shutdownNow() method.
For example:
for (int i = 0; i < noOfThreads; i++) {
service.submit(new ThreadTask());
}
// we always need to shutdown the service _after_ we've submitted all jobs
service.shutdown();
// now we wait for those tasks to finish for 10 minutes
if (!service.awaitTermination(10, TimeUnit.MINUTES)) {
// if we timed out waiting for the tasks to finish, forcefully interrupt them
service.shutdownNow();
}
Note that this will interrupt the threads but that will only cause certain methods such as Thread.sleep(), Object.wait(), and some others to throw InterruptedException. It also sets the interrupt bit on the thread which can be tested with Thread.currentThread().isInterrupted(). It will not "kill" the thread like you would a unix process.
How do I notify my main class which instantiates a ThreadPoolExecutor when all threads within the ThreadPoolExecutor are completed?
ThreadPoolExecutor threadPool = null;
ThreadClass threadclass1;
ThreadClass threadclass2;
final ArrayBlockingQueue<Runnable> queue = new ArrayBlockingQueue<Runnable>(maxPoolSize);
puclic MyClass(){
threadPool = new ThreadPoolExecutor(poolSize, maxPoolSize, keepAliveTime, TimeUnit.SECONDS, queue);
threadClass1 = new ThreadClass;
threadClass2 = new ThreadClass;
threadPool.execute(threadClass1);
threadPool.execute(threadClass2);
//Now I would like to do something until the threadPool is done working
//The threads fill a ConcurrentLinkedQueueand I would like to poll
//the queue as it gets filled by the threads and output
//it to XML via JAX-RS
}
EDIT 1
Wile my threads fetch data from somewhere and fill this information into a ConcurrentLinkedQueue I basically would like to perform some action in MyClass to update the XML output with the results. When all threads are terminated I would like to return true to the JAX-RS webservice which instantiated MyClass so the webservice knows all data has been fetched and it can now display the final XML file
EDIT 2
I am passing a Queue to threads so they can add items to the queue. When one driver is done adding items to the articleQueue I want to perform an action within my main class, polling the entity from the Queue and handing it over to the response object to display it in some way.
When I pass the queue to the threads, are they working with the same object or with a "copy" of the object so that changes within the thread do not effect the main object? That is not the behavior I want. When I check the size of the articleQueue within the Driver it is 18, the size of the articleQueue in the DriverController is 0.
Is there a nicer way to react when a thread has added something to the queue other than my while loop? How do I have to modify my code to acces the same object within different classes?
DriverController
public class DriverController {
Queue<Article> articleQueue;
ThreadPoolExecutor threadPool = null;
final ArrayBlockingQueue<Runnable> queue = new ArrayBlockingQueue<Runnable>(
maxPoolSize);
public DriverController(Response response) {
articleQueue = new ConcurrentLinkedQueue<Article>();
threadPool = new ThreadPoolExecutor();
Driver driver = new Driver(this.articleQueue);
threadPool.execute(driver);
// More drivers would be executed here which add to the queue
while (threadPool.getActiveCount() > 0) {
// this.articleQueue.size() gives back 0 here ... why?
if(articleQueue.size()>0){
response.addArticle(articleQueue.poll());
}
}
}
}
Driver
public class Driver implements Runnable{
private Queue<Article> articleQueue;
public DriverAlliedElectronics(Queue articleQueue) {
this.articleQueue = articleQueue;
}
public boolean getData() {
// Here would be the code where the article is created ...
this.articleQueue.offer(article);
return true;
}
public void run() {
this.getData();
// this.articleQueue.size() gives back 18 here ...
}
}
You should try to use following snippet
//Now I would like to wait until the threadPool is done working
threadPool.shutdown();
while (!threadPool.isTerminated()) {
try {
threadPool.awaitTermination(10, TimeUnit.MILLISECONDS);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
Maybe a ExecutorCompletionService might be the right thing for you:
http://download.oracle.com/javase/1.5.0/docs/api/java/util/concurrent/ExecutorCompletionService.html
Example from the link above:
void solve(Executor e, Collection<Callable<Result>> solvers)
throws InterruptedException, ExecutionException {
CompletionService<Result> ecs = new ExecutorCompletionService<Result>(e);
for (Callable<Result> s : solvers)
ecs.submit(s);
int n = solvers.size();
for (int i = 0; i < n; ++i) {
Result r = ecs.take().get();
if (r != null)
use(r);
}
}
Instead of using execute you should use submit. This will return a Future instance on which you can wait for the task(s) to complete. That way you don't need polling or shutting down the pool.
I don't think there's a way to do this explicitly. You could poll the getCompletedTaskCount() to wait for that to become zero.
Why not collect the Future objects returned upon submission and check for all of those being completed ? Simply call get() on each one in turn. Since that call blocks you'll simply wait for each in turn and gradually fall through the set until you've waited on each on.
Alternatively you could submit the threads, and call shutdown() on the executor. That way, the submitted tasks will be executed, and then the terminated() method is called. If you override this then you'll get a callback once all tasks are completed (you couldn't use that executor again, obviously).
Judging from the reference documentation you have a few options:
ThreadPoolExecutor threadPool = null;
ThreadClass threadclass1;
ThreadClass threadclass2;
final ArrayBlockingQueue<Runnable> queue = new ArrayBlockingQueue<Runnable>(maxPoolSize);
puclic MyClass(){
threadPool = new ThreadPoolExecutor(poolSize, maxPoolSize, keepAliveTime, TimeUnit.SECONDS, queue);
threadClass1 = new ThreadClass;
threadClass2 = new ThreadClass;
threadPool.execute(threadClass1);
threadPool.execute(threadClass2);
//Now I would like to wait until the threadPool is done working
//Option 1: shutdown() and awaitTermination()
threadPool.shutDown();
try {
threadPool.awaitTermination(Long.MAX_VALUE, TimeUnit.SECONDS)
}
catch (InterruptedException e) {
e.printStackTrace();
}
//Option 2: getActiveCount()
while (threadPool.getActiveCount() > 0) {
try {
Thread.sleep(1000);
}
catch (InterruptedException ignored) {}
}
//Option 3: getCompletedTaskCount()
while (threadPool.getCompletedTaskCount() < totalNumTasks) {
try {
Thread.sleep(1000);
}
catch (InterruptedException ignored) {}
}
}
All things considered, I think shutdown() and awaitTermination() is the best option of the three.
I think you're overengineering things a bit. You don't really care about the threads or the thread pool, and rightly so. Java provides nice abstractions so that you don't have to. You just need to know when your tasks are complete, and methods exist for that. Just submit your jobs, and wait for the futures to say they're done. If you really want to know as soon as a single task completes, you can watch all the futures and take action as soon as any one is finished. If not and you only care that everything is finished, you can remove some complexity from the code I'm about to post. Try this on for size (note MultithreadedJaxrsResource is executable):
import javax.ws.rs.*;
import javax.ws.rs.core.MediaType;
import java.util.*;
import java.util.concurrent.*;
#Path("foo")
public class MultithreadedJaxrsResource {
private ExecutorService executorService;
public MultithreadedJaxrsResource(ExecutorService executorService) {
this.executorService = executorService;
}
#GET
#Produces(MediaType.APPLICATION_XML)
public AllMyArticles getStuff() {
List<Future<Article>> futures = new ArrayList<Future<Article>>();
// Submit all the tasks to run
for (int i = 0; i < 10; i++) {
futures.add(executorService.submit(new Driver(i + 1)));
}
AllMyArticles articles = new AllMyArticles();
// Wait for all tasks to finish
// If you only care that everything is done and not about seeing
// when each one finishes, this outer do/while can go away, and
// you only need a single for loop to wait on each future.
boolean allDone;
do {
allDone = true;
Iterator<Future<Article>> futureIterator = futures.iterator();
while (futureIterator.hasNext()) {
Future<Article> future = futureIterator.next();
if (future.isDone()) {
try {
articles.articles.add(future.get());
futureIterator.remove();
} catch (InterruptedException e) {
// thread was interrupted. don't do that.
throw new IllegalStateException("broken", e);
} catch (ExecutionException e) {
// execution of the Callable failed with an
// exception. check it out.
throw new IllegalStateException("broken", e);
}
} else {
allDone = false;
}
}
} while (!allDone);
return articles;
}
public static void main(String[] args) {
ExecutorService executorService = Executors.newFixedThreadPool(10);
AllMyArticles stuff =
new MultithreadedJaxrsResource(executorService).getStuff();
System.out.println(stuff.articles);
executorService.shutdown();
}
}
class Driver implements Callable<Article> {
private int i; // Just to differentiate the instances
public Driver(int i) {
this.i = i;
}
public Article call() {
// Simulate taking some time for each call
try {
Thread.sleep(1000 / i);
} catch (InterruptedException e) {
System.err.println("oops");
}
return new Article(i);
}
}
class AllMyArticles {
public final List<Article> articles = new ArrayList<Article>();
}
class Article {
public final int i;
public Article(int i) {
this.i = i;
}
#Override
public String toString() {
return "Article{" +
"i=" + i +
'}';
}
}
Done that way, you can plainly see that the tasks are returned in the order they complete, as the last task finishes first thanks to sleeping the shortest time. If you don't care about completion order and just want to wait for all to finish, the loop becomes much simpler:
for (Future<Article> future : futures) {
try {
articles.articles.add(future.get());
} catch (InterruptedException e) {
// thread was interrupted. don't do that.
throw new IllegalStateException("broken", e);
} catch (ExecutionException e) {
// execution of the Callable failed with an exception. check it out.
throw new IllegalStateException("broken", e);
}
}
I am trying to execute lots of tasks using a ThreadPoolExecutor. Below is a hypothetical example:
def workQueue = new ArrayBlockingQueue<Runnable>(3, false)
def threadPoolExecutor = new ThreadPoolExecutor(3, 3, 1L, TimeUnit.HOURS, workQueue)
for(int i = 0; i < 100000; i++)
threadPoolExecutor.execute(runnable)
The problem is that I quickly get a java.util.concurrent.RejectedExecutionException since the number of tasks exceeds the size of the work queue. However, the desired behavior I am looking for is to have the main thread block until there is room in the queue. What is the best way to accomplish this?
In some very narrow circumstances, you can implement a java.util.concurrent.RejectedExecutionHandler that does what you need.
RejectedExecutionHandler block = new RejectedExecutionHandler() {
rejectedExecution(Runnable r, ThreadPoolExecutor executor) {
executor.getQueue().put( r );
}
};
ThreadPoolExecutor pool = new ...
pool.setRejectedExecutionHandler(block);
Now. This is a very bad idea for the following reasons
It's prone to deadlock because all the threads in the pool may die before the thing you put in the queue is visible. Mitigate this by setting a reasonable keep alive time.
The task is not wrapped the way your Executor may expect. Lots of executor implementations wrap their tasks in some sort of tracking object before execution. Look at the source of yours.
Adding via getQueue() is strongly discouraged by the API, and may be prohibited at some point.
A almost-always-better strategy is to install ThreadPoolExecutor.CallerRunsPolicy which will throttle your app by running the task on the thread which is calling execute().
However, sometimes a blocking strategy, with all its inherent risks, is really what you want. I'd say under these conditions
You only have one thread calling execute()
You have to (or want to) have a very small queue length
You absolutely need to limit the number of threads running this work (usually for external reasons), and a caller-runs strategy would break that.
Your tasks are of unpredictable size, so caller-runs could introduce starvation if the pool was momentarily busy with 4 short tasks and your one thread calling execute got stuck with a big one.
So, as I say. It's rarely needed and can be dangerous, but there you go.
Good Luck.
What you need to do is to wrap your ThreadPoolExecutor into Executor which explicitly limits amount of concurrently executed operations inside it:
private static class BlockingExecutor implements Executor {
final Semaphore semaphore;
final Executor delegate;
private BlockingExecutor(final int concurrentTasksLimit, final Executor delegate) {
semaphore = new Semaphore(concurrentTasksLimit);
this.delegate = delegate;
}
#Override
public void execute(final Runnable command) {
try {
semaphore.acquire();
} catch (InterruptedException e) {
e.printStackTrace();
return;
}
final Runnable wrapped = () -> {
try {
command.run();
} finally {
semaphore.release();
}
};
delegate.execute(wrapped);
}
}
You can adjust concurrentTasksLimit to the threadPoolSize + queueSize of your delegate executor and it will pretty much solve your problem
You could use a semaphore to block threads from going into the pool.
ExecutorService service = new ThreadPoolExecutor(
3,
3,
1,
TimeUnit.HOURS,
new ArrayBlockingQueue<>(6, false)
);
Semaphore lock = new Semaphore(6); // equal to queue capacity
for (int i = 0; i < 100000; i++ ) {
try {
lock.acquire();
service.submit(() -> {
try {
task.run();
} finally {
lock.release();
}
});
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
}
Some gotchas:
Only use this pattern with a fixed thread pool. The queue is unlikely to be full often, thus new threads won't be created. Check out the java docs on ThreadPoolExecutor for more details: https://docs.oracle.com/javase/8/docs/api/java/util/concurrent/ThreadPoolExecutor.html There is a way around this, but it is out of scope of this answer.
Queue size should be higher than the number of core threads. If we were to make the queue size 3, what would end up happening is:
T0: all three threads are doing work, the queue is empty, no permits are available.
T1: Thread 1 finishes, releases a permit.
T2: Thread 1 polls the queue for new work, finds none, and waits.
T3: Main thread submits work into the pool, thread 1 starts work.
The example above translates to thread the main thread blocking thread 1. It may seem like a small period, but now multiply the frequency by days and months. All of a sudden, short periods of time add up to a large amount of time wasted.
This is what I ended up doing:
int NUM_THREADS = 6;
Semaphore lock = new Semaphore(NUM_THREADS);
ExecutorService pool = Executors.newCachedThreadPool();
for (int i = 0; i < 100000; i++) {
try {
lock.acquire();
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
pool.execute(() -> {
try {
// Task logic
} finally {
lock.release();
}
});
}
A fairly straightforward option is to wrap your BlockingQueue with an implementation that calls put(..) when offer(..) is being invoked:
public class BlockOnOfferAdapter<T> implements BlockingQueue<T> {
(..)
public boolean offer(E o) {
try {
delegate.put(o);
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
return false;
}
return true;
}
(.. implement all other methods simply by delegating ..)
}
This works because by default put(..) waits until there is capacity in the queue when it is full, see:
/**
* Inserts the specified element into this queue, waiting if necessary
* for space to become available.
*
* #param e the element to add
* #throws InterruptedException if interrupted while waiting
* #throws ClassCastException if the class of the specified element
* prevents it from being added to this queue
* #throws NullPointerException if the specified element is null
* #throws IllegalArgumentException if some property of the specified
* element prevents it from being added to this queue
*/
void put(E e) throws InterruptedException;
No catching of RejectedExecutionException or complicated locking necessary.
Here is my code snippet in this case:
public void executeBlocking( Runnable command ) {
if ( threadPool == null ) {
logger.error( "Thread pool '{}' not initialized.", threadPoolName );
return;
}
ThreadPool threadPoolMonitor = this;
boolean accepted = false;
do {
try {
threadPool.execute( new Runnable() {
#Override
public void run() {
try {
command.run();
}
// to make sure that the monitor is freed on exit
finally {
// Notify all the threads waiting for the resource, if any.
synchronized ( threadPoolMonitor ) {
threadPoolMonitor.notifyAll();
}
}
}
} );
accepted = true;
}
catch ( RejectedExecutionException e ) {
// Thread pool is full
try {
// Block until one of the threads finishes its job and exits.
synchronized ( threadPoolMonitor ) {
threadPoolMonitor.wait();
}
}
catch ( InterruptedException ignored ) {
// return immediately
break;
}
}
} while ( !accepted );
}
threadPool is a local instance of java.util.concurrent.ExecutorService which has been initialized already.
I solved this problem using a custom RejectedExecutionHandler, which simply blocks the calling thread for a little while and then tries to submit the task again:
public class BlockWhenQueueFull implements RejectedExecutionHandler {
public void rejectedExecution(Runnable r, ThreadPoolExecutor executor) {
// The pool is full. Wait, then try again.
try {
long waitMs = 250;
Thread.sleep(waitMs);
} catch (InterruptedException interruptedException) {}
executor.execute(r);
}
}
This class can just be used in the thread-pool executor as a RejectedExecutionHandler like any other. In this example:
executorPool = new def threadPoolExecutor = new ThreadPoolExecutor(3, 3, 1L, TimeUnit.HOURS, workQueue, new BlockWhenQueueFull())
The only downside I see is that the calling thread might get locked slightly longer than strictly necessary (up to 250ms). For many short-running tasks, perhaps decrease the wait-time to 10ms or so. Moreover, since this executor is effectively being called recursively, very long waits for a thread to become available (hours) might result in a stack overflow.
Nevertheless, I personally like this method. It's compact, easy to understand, and works well. Am I missing anything important?
Ok, old thread but this is what I found when searching for blocking thread executor. My code tries to get a semaphore when the task is submitted to the task queue. This blocks if there are no semaphores left. As soon as a task is done the semaphore is released with the decorator. Scary part is that there is a possibility of losing semaphore but that could be solved with for example a timed job that just clears semaphores on a timed basis.
So here my solution:
class BlockingThreadPoolTaskExecutor(concurrency: Int) : ThreadPoolTaskExecutor() {
companion object {
lateinit var semaphore: Semaphore
}
init {
semaphore = Semaphore(concurrency)
val semaphoreTaskDecorator = SemaphoreTaskDecorator()
this.setTaskDecorator(semaphoreTaskDecorator)
}
override fun <T> submit(task: Callable<T>): Future<T> {
log.debug("submit")
semaphore.acquire()
return super.submit(task)
}
}
private class SemaphoreTaskDecorator : TaskDecorator {
override fun decorate(runnable: Runnable): Runnable {
log.debug("decorate")
return Runnable {
try {
runnable.run()
} finally {
log.debug("decorate done")
semaphore.release()
}
}
}
}
One could overwrite ThreadPoolExecutor.execute(command) to use a Semaphore, e.g.:
/**
* The setup answering the question needs to have:
*
* permits = 3
* corePoolSize = permits (i.e. 3)
* maximumPoolSize = corePoolSize (i.e. 3)
* workQueue = anything different to null
*
* With this setup workQueue won’t actually be used but only
* to check if it’s empty, which should always be the case.
* Any more than permits as value for maximumPoolSize will have
* no effect because at any moment no more than permits calls to
* super.execute() will be allowed by the semaphore.
*/
public class ExecutionBlockingThreadPool extends ThreadPoolExecutor {
private final Semaphore semaphore;
// constructor setting super(…) parameters and initializing semaphore
//
// Below is a bare minimum constructor; using
// corePoolSize = maximumPoolSize = permits
// allows one to use SynchronousQueue because I expect
// none other that isEmpty() to be called on it; it also
// allows for using 0L SECONDS because no more than
// corePoolSize threads should be attempted to create.
public ExecutionBlockingThreadPool(int corePoolSize) {
super(corePoolSize, corePoolSize, 0L, SECONDS, new SynchronousQueue<Runnable>());
semaphore = new Semaphore(corePoolSize, true);
}
public void execute(Runnable command) {
semaphore.acquire();
super.execute(() -> {
try {
command.run();
} finally {
semaphore.release();
}
}
}
}
You can imlement RejectedTaskHandler and get all the rejected tasks when Queue size if full. By default executors have the Abort policy so you can add these task back to the queue from handler or whatever the choice is.
public class ExecutorRejectedTaskHandlerFixedThreadPool {
public static void main(String[] args) throws InterruptedException {
//maximum queue size : 2
BlockingQueue<Runnable> blockingQueue =
new LinkedBlockingQueue<Runnable>(2);
CustomThreadPoolExecutor executor =
new CustomThreadPoolExecutor(4, 5, 5, TimeUnit.SECONDS,
blockingQueue);
RejectedTaskHandler rejectedHandler = new RejectedTaskHandler();
executor.setRejectedExecutionHandler(rejectedHandler);
//submit 20 the tasks for execution
//Note: only 7 tasks(5-max pool size + 2-queue size) will be executed and rest will be rejected as queue will be overflowed
for (int i = 0; i < 20; i++) {
executor.execute(new Task());
}
System.out.println("Thread name " + Thread.currentThread().getName());
}
static class Task implements Runnable {
#Override
public void run() {
try {
Thread.sleep(500);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("Thread - " + Thread.currentThread().getName() + " performing it's job");
}
}
static class RejectedTaskHandler implements RejectedExecutionHandler {
#Override
public void rejectedExecution(Runnable r, ThreadPoolExecutor executor) {
System.out.println("Task rejected" + r.toString());
}
}
public static class CustomThreadPoolExecutor extends ThreadPoolExecutor {
public CustomThreadPoolExecutor(int corePoolSize, int maximumPoolSize,
long keepAliveTime, TimeUnit unit,
BlockingQueue<Runnable> workQueue) {
super(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue);
}
#Override
protected void beforeExecute(Thread t, Runnable r) {
super.beforeExecute(t, r);
}
#Override
protected void afterExecute(Runnable r, Throwable t) {
super.afterExecute(r, t);
}
}
}