Reputation: 1372
While using java.util.concurrent.ThreadPoolExecutor
I wanted to try to execute a rejected task once more.
Is it really possible? I have heard of RejectedExecutionHandler
interface. There are many available(known) instances of the interface(RejectedExecutionHandler) such as ThreadPoolExecutor.AbortPolicy, ThreadPoolExecutor.CallerRunsPolicy, ThreadPoolExecutor.DiscardOldestPolicy, ThreadPoolExecutor.DiscardPolicy etc. but the problem is that they do not allow to retry the execution.
Upvotes: 3
Views: 9339
Reputation: 703
I'll add few points to the comment by @Viscent Huang.
First, this solution makes sense only if your ThreadPoolExecutor
is using BlockingQueue
.
Second, this solution also provides risk that you may have a deadlock in case your threadpool is full because you're inserting runnable in a blocking manner in a threadpool which might be already filled.
For example this code may easily cause such problem:
CompletableFuture.supplyAsync(
() -> {
// some computation intensive task
}, executors
).thenAcceptAsync(
res -> {
// handling the result
}, executors);
What I suggest is to handle rejected threads in a separate threadpool to avoid deadlock. So finally your code may look like this:
public class CustomRejectedExecutionHandler implements RejectedExecutionHandler {
private final Executor rejectedExecutionThread = Executors.newFixedThreadPool(1);
@Override
public void rejectedExecution(Runnable r, ThreadPoolExecutor executor) {
rejectedExecutionThread.execute(() -> {
try {
executor.getQueue().put(r);
} catch (Exception e) {
// handle exception
}
});
}
}
Upvotes: 0
Reputation: 71
Below is a retry-enabled RejectedExecutionHandler that does not require an additional ThreadPoolExecutor. It's is more practical: when a task was rejected, the rejected task will be put into the workerQueue of ThreadPoolExecutor in blocking mode, which makes the task submitter wait some time before the ThreadPoolExecutor can process any more tasks.
new RejectedExecutionHandler() {
@Override
public void rejectedExecution(Runnable r, ThreadPoolExecutor executor) {
if (!executor.isShutdown()) {
try {
executor.getQueue().put(r);
} catch (InterruptedException e) {
;
}
}
}
}
Upvotes: 7
Reputation: 1372
Yes it is possible to retry the execution of the rejected task. The best way to retry the execution is to use an alternate executor. You may declare a custom RejectedExecutionHandler class simply like as you do this with other interfaces. Here are some code samples:
public class MyRejectedExecutionHandler implements RejectedExecutionHandler {
@Override
public void rejectedExecution(Runnable worker, ThreadPoolExecutor executor) {
// TODO Auto-generated method stub
System.out.println(worker.toString()+" is Rejected");
System.out.println("Retrying to Execute");
try{
//Re-executing with alternateExecutor
MainClass.alternateExecutor.execute(worker);
System.out.println(worker.toString()+" Execution Started");
}
catch(Exception e)
{
System.out.println("Failure to Re-exicute "+e.getMessage());
}
}
}
You can find more details about this at: http://examples.javacodegeeks.com/core-java/util/concurrent/rejectedexecutionhandler/java-util-concurrent-rejectedexecutionhandler-example/
Upvotes: 2