Exception handling with multiple futures from ScheduledExecutorService - java

I am using a ScheduledExecutorService to which I add both submit Runnables as well as scheduled Runnables (using scheduleWithFixedDelay).
The intention is to have very long running processes and thus non of my runnables have a defined lifetime. I basically want the main thread to only react to exceptions and interruptions.
The scheduled tasks are critical, e.g. generating heatbeats, and thus if any thread throw a runtimeexception I want to log the exception, abort all other threads and close the program.
How should I handle the exceptions? The ScheduledExecutorService swallows all the exceptions unless I run Future.get().
Looping through the futures, like below, does not work. If the first item in the futures list doesn't return any errors that will block the thread from listening on the other threads that might return error.
for (Future<?> future : futures) {
future.get();
}
One option would be looping through the futures asking if they are done, like below, but I don't really like this solution. I need to add a thread sleep and thus the response to an exception is delayed.
boolean allActive = true;
while (allActive) {
for (Future<?> future : futures) {
if (!future.isDone()) {
allActive = false;
break;
}
}
Thread.sleep(50);
}
What other options do I have? Or am I approaching the problem wrong?
Shouldn't I use a ScheduledExecutorService at all and implement the schedule myself in my own thread?
Example code, try change the order to the future list! I want the behavior you get if you add handle before handle2 but the order of the list shouldn't matter:
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;
public class Test {
private static int i = 0;
public static void main(String[] args) throws Exception {
ScheduledExecutorService scheduler = Executors.newSingleThreadScheduledExecutor();
Future<?> handle = scheduler.scheduleWithFixedDelay(new Runnable() {
public void run() {
System.out.println("No exception!");
if (i > 2) {
System.out.println("Exception!");
throw new RuntimeException("foo");
}
i++;
}
}, 0, 500, TimeUnit.MILLISECONDS);
Future<?> handle2 = scheduler.scheduleWithFixedDelay(new Runnable() {
public void run() {
System.out.println("Running!");
}
}, 0, 500, TimeUnit.MILLISECONDS);
List<Future<?>> futures = new ArrayList<>();
futures.add(handle2);
futures.add(handle);
try {
for (Future<?> future : futures) {
future.get();
}
} catch (Exception e) {
scheduler.shutdownNow();
System.out.println(scheduler.awaitTermination(1, TimeUnit.SECONDS));
System.out.println("Shuwdown complete");
e.printStackTrace();
}
}
}

You can do it with a Listener or Observer-Like pattern:
interface IFutureListener{
void onException( Throwable t );
}
final IFutureListener errHandler = new IFutureListener(){
#override public void onException( Throwable t ){
// shutdown Service here
}
};
// ...
Future<?> handle = scheduler.scheduleWithFixedDelay(new Runnable() {
final IFutureListener callback = errHandler;
public void run() {
try{
System.out.println("No exception!");
if (i > 2) {
System.out.println("Exception!");
throw new RuntimeException("foo");
}
i++;
}
catch( Exception ex ){
callback.onException(ex);
}
}
}, 0, 500, TimeUnit.MILLISECONDS);
You still might need some tweaks to this, but this is the gist of it.
Guava's ListenableFuture as #dimo414 writes in comment will give you something similar. But if you do not want / are not allowed to use 3rd parties, this is a way you can implement it yourself.
Thanks to #efekctive: I also suggest logging exceptions. They should almost never just be swallowed silently except you know exactly what you are doing.

Related

SimpleAsyncTaskExecutor with a queue

I have a need to run some threads concurrently, but need to force each process to run in a new Thread (this is due to some ThreadLocal bleed that I don't have full control over). To do so, I have been using the SimpleAsyncTaskExecutor. However, the issue with this is that it doesn't maintain a queue that allows new tasks to be submitted once it's reached the concurrency limit. What I really need to do is have functionality like the SimpleAsyncTaskExecutor but where tasks can still be submitted even after the concurrency limit has been reached - I just want those tasks to wait in the queue until another slot frees up. This is what I have right now:
SimpleAsyncTaskExecutor taskExecutor = new SimpleAsyncTaskExecutor();
taskExecutor.setConcurrencyLimit(maxThreads);
return taskExecutor;
Is there some out-of-the-box solution for this, or do I need to write something custom?
To ensure you need to execute every task in a new Thread, You are basically against use of any ThreadPool (ThreadLocal behavior in a ThreadPool is something you need to get rid of, sooner or later).
To overcome this, you can simply produce something like this,
class ThreadPerTaskExecutor implements Executor {
public void execute(Runnable r) {
Thread t = new Thread(r);
t.start();
try {
t.join();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
which executes the Runnable always in a new Thread.
Coming to a crude implementation, We can do something like
final Executor executor = new ThreadPerTaskExecutor();
final ExecutorService service = Executors.newFixedThreadPool(3);
for (int i = 0; i < 100; i++) {
service.submit(new Runnable() {
public void run() {
try {
System.out.println("Executed inside Thread pool with concurrency level 3"
+ Thread.currentThread().toString());
executor.execute(new Runnable() {
public void run() {
try {
Thread.sleep(3000); //Some expensive operations here.
System.out.println(
"Executed inside new Thread always" + Thread.currentThread().toString());
} catch (InterruptedException e) {
e.printStackTrace();
}
}
});
} catch (Exception e) {
e.printStackTrace();
}
}
});
}
This can be improved with lambdas as well after Java 8. Hope this sheds the basic idea.
Is there some out-of-the-box solution for this, or do I need to write something custom?
I think there is no out-of-the-box solution for this, and you need to write your own code for this.
You can extend the SimpleAsyncTaskExecutor for simpler/quicker implementation. Example:
public class SimpleAsyncQueueTaskExecutor extends SimpleAsyncTaskExecutor {
private Queue<Runnable> queue = new ConcurrentLinkedQueue<Runnable>();
private AtomicInteger concurrencyValue = new AtomicInteger(0);
private void checkAndExecuteFromQueue() {
int count = concurrencyValue.get();
if (isThrottleActive() && !queue.isEmpty() &&
(count < getConcurrencyLimit())) {
Runnable task = queue.poll();
concurrencyValue.incrementAndGet();
doExecute(new ConcurrencyThrottlingRunnable(task));
}
}
private void afterExecute(Runnable task) {
queue.remove(task);
concurrencyValue.decrementAndGet();
// Check and execute other tasks
checkAndExecuteFromQueue();
}
#Override
public void execute(Runnable task, long startTimeout) {
Assert.notNull(task, "Runnable must not be null");
if (isThrottleActive() && startTimeout > TIMEOUT_IMMEDIATE) {
queue.offer(task);
checkAndExecuteFromQueue();
} else {
doExecute(task);
}
}
private class ConcurrencyThrottlingRunnable implements Runnable {
private final Runnable target;
public ConcurrencyThrottlingRunnable(Runnable target) {
this.target = target;
}
#Override
public void run() {
try {
this.target.run();
}
finally {
afterExecute(this.target);
}
}
}
This example code just add a queue, and override the execute method.
Hope this help.

How to terminate callable process called by ExecutorService

In the following code I want to terminate the Callable process submitted by ExecutorService. Currently the execution of the callable process is not terminating even though the shutdown called before the loop execution.
Any suggestion would be helpful.
package foundation.util.sql.parser;
import java.io.IOException;
import java.util.HashMap;
import java.util.concurrent.*;
public class Test {
public static void main(String[] args) {
try {
final java.util.Map<String, ExecutorService> map = new HashMap<>();
ExecutorService service = Executors.newFixedThreadPool(1);
map.put("1", service);
Thread thread = new Thread(new Runnable() {
#Override
public void run() {
try {
System.out.println("Termination Initiated");
ExecutorService executorService = map.get("1");
System.out.println("ShutDown called");
if(!executorService.isShutdown())
{
executorService.shutdownNow();
}
} catch (Exception e) {
e.printStackTrace();
}
}
});
Future<Boolean> submit = service.submit(new Callable<Boolean>() {
#Override
public Boolean call() throws Exception {
int j = 0;
System.out.println(Thread.currentThread().getName());
for (int i=0; i<5000;i++) {
//Some business Process.
j = i;
}
System.out.println("Test____"+ j);
return null;
}
});
thread.start();
submit.get();
} catch (Exception e) {
e.printStackTrace();
}
}
}
When we call showDownNow() it doesn't terminate the running tasks, in fact
it just prevents waiting tasks from starting and attempts to stop currently executing tasks.
As per javadoc
There are no guarantees beyond best-effort attempts to stop processing actively executing tasks. For example, typical implementations will cancel via Thread.interrupt(), so any task that fails to respond to interrupts may never terminate.
In your callable you are not responding/checking for the interrupts. You need check periodically if the interrupt flag is set to true. If so, do the necessary clean up if needed and terminate.
As an example, in your case you can consider checking the interrupt flag as below (or wherever applicable):
for (int i=0; i<5000;i++) {
//Some business Process.
if(Thread.currentThread().isInterrupted()) {
// do any cleanup and return from here.
return false;
}
j = i;
}

Java: notify main class when all threads in threadpool are finished / same instance of object in different threads

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);
}
}

ScheduledExecutorService Exception handling

I use ScheduledExecutorService to execute a method periodically.
p-code:
ScheduledExecutorService scheduler = Executors.newSingleThreadScheduledExecutor();
ScheduledFuture<?> handle =
scheduler.scheduleWithFixedDelay(new Runnable() {
public void run() {
//Do business logic, may Exception occurs
}
}, 1, 10, TimeUnit.SECONDS);
My question:
How to continue the scheduler, if run() throws Exception?
Should I try-catch all Exception in method run()? Or any built-in callback method to handle the Exception? Thanks!
tl;dr
Any exception escaping your run method halts all further work, without notice.
Always use a try-catch within your run method. Try to recover if you want scheduled activity to continue.
#Override
public void run ()
{
try {
doChore();
} catch ( Exception e ) {
logger.error( "Caught exception in ScheduledExecutorService. StackTrace:\n" + t.getStackTrace() );
}
}
The Problem
The question refers to the critical trick with a ScheduledExecutorService: Any thrown exception or error reaching the executor causes the executor to halt. No more invocations on the Runnable, no more work done. This work stoppage happens silently, you'll not be informed. This naughty-language blog posting entertainingly narrates the hard way to learn about this behavior.
The Solution
The answer by yegor256 and the answer by arun_suresh both seem to be basically correct. Two issues with those answers:
Catch errors as well as exceptions
A bit complicated
Errors and Exceptions ?
In Java we normally catch only exceptions, not errors. But in this special case of ScheduledExecutorService, failing to catch either will mean a work stoppage. So you may want to catch both. I'm not 100% sure about this, not knowing fully the implications of catching all errors. Please correct me if needed.
One reason to catch errors as well as exceptions might involve the use of libraries within your task. See the comment by jannis.
One way to catch both exceptions and errors is to catch their superclass, Throwable for an example.
} catch ( Throwable t ) {
…rather than…
} catch ( Exception e ) {
Simplest Approach: Just Add a Try-Catch
But both answers are a bit complicated. Just for the record, I'll show the simplest solution:
Always wrap your Runnable's code in a Try-Catch to catch any and all exceptions and errors.
Lambda Syntax
With a lambda (in Java 8 and later).
final Runnable someChoreRunnable = () -> {
try {
doChore();
} catch ( Throwable t ) { // Catch Throwable rather than Exception (a subclass).
logger.error( "Caught exception in ScheduledExecutorService. StackTrace:\n" + t.getStackTrace() );
}
};
Old-Fashioned Syntax
The old-fashioned way, before lambdas.
final Runnable someChoreRunnable = new Runnable()
{
#Override
public void run ()
{
try {
doChore();
} catch ( Throwable t ) { // Catch Throwable rather than Exception (a subclass).
logger.error( "Caught exception in ScheduledExecutorService. StackTrace:\n" + t.getStackTrace() );
}
}
};
In Every Runnable/Callable
Regardless of a ScheduledExecutorService, it seems sensible to me to always use a general try-catch( Exception† e ) in any run method of a Runnable. Ditto for any call method of a Callable.
Complete example code
In real work, I would likely define the Runnable separately rather than nested. But this makes for neat all-in-one example.
package com.basilbourque.example;
import java.time.ZoneId;
import java.time.ZonedDateTime;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.ScheduledFuture;
import java.util.concurrent.TimeUnit;
/**
* Demo `ScheduledExecutorService`
*/
public class App {
public static void main ( String[] args ) {
App app = new App();
app.doIt();
}
private void doIt () {
// Demonstrate a working scheduled executor service.
// Run, and watch the console for 20 seconds.
System.out.println( "BASIL - Start." );
ScheduledExecutorService scheduler = Executors.newSingleThreadScheduledExecutor();
ScheduledFuture < ? > handle =
scheduler.scheduleWithFixedDelay( new Runnable() {
public void run () {
try {
// doChore ; // Do business logic.
System.out.println( "Now: " + ZonedDateTime.now( ZoneId.systemDefault() ) ); // Report current moment.
} catch ( Exception e ) {
// … handle exception/error. Trap any unexpected exception here rather to stop it reaching and shutting-down the scheduled executor service.
// logger.error( "Caught exception in ScheduledExecutorService. StackTrace:\n" + e.getStackTrace() );
} // End of try-catch.
} // End of `run` method.
} , 0 , 2 , TimeUnit.SECONDS );
// Wait a long moment, for background thread to do some work.
try {
Thread.sleep( TimeUnit.SECONDS.toMillis( 20 ) );
} catch ( InterruptedException e ) {
e.printStackTrace();
}
// Time is up. Kill the executor service and its thread pool.
scheduler.shutdown();
System.out.println( "BASIL - Done." );
}
}
When run.
BASIL - Start.
Now: 2018-04-10T16:46:01.423286-07:00[America/Los_Angeles]
Now: 2018-04-10T16:46:03.449178-07:00[America/Los_Angeles]
Now: 2018-04-10T16:46:05.450107-07:00[America/Los_Angeles]
Now: 2018-04-10T16:46:07.450586-07:00[America/Los_Angeles]
Now: 2018-04-10T16:46:09.456076-07:00[America/Los_Angeles]
Now: 2018-04-10T16:46:11.456872-07:00[America/Los_Angeles]
Now: 2018-04-10T16:46:13.461944-07:00[America/Los_Angeles]
Now: 2018-04-10T16:46:15.463837-07:00[America/Los_Angeles]
Now: 2018-04-10T16:46:17.469218-07:00[America/Los_Angeles]
Now: 2018-04-10T16:46:19.473935-07:00[America/Los_Angeles]
BASIL - Done.
Another example
Here is another example. Here our task is meant to run about twenty times, once every five seconds for a minute. But on the fifth run, we throw an exception.
public class App2
{
public static void main ( String[] args )
{
ScheduledExecutorService ses = Executors.newSingleThreadScheduledExecutor();
final AtomicInteger counter = new AtomicInteger( 0 );
Runnable task = ( ) -> {
int c = counter.incrementAndGet();
if ( c > 4 )
{
System.out.println( "THROWING EXCEPTION at " + Instant.now() );
throw new IllegalStateException( "Bogus exception. c = " + c + ". " + Instant.now() ); // Notice how this exception is silently swallowed by the scheduled executor service, while causing a work stoppage.
}
System.out.println( "Task running. c = " + c + ". " + Instant.now() );
};
ses.scheduleAtFixedRate( task , 0 , 5 , TimeUnit.SECONDS );
try { Thread.sleep( Duration.ofMinutes( 1 ).toMillis() ); }catch ( InterruptedException e ) { e.printStackTrace(); }
System.out.println( "Main thread done sleeping. " + Instant.now() );
ses.shutdown();
try { ses.awaitTermination( 1 , TimeUnit.MINUTES ); }catch ( InterruptedException e ) { e.printStackTrace(); }
}
}
When run.
Task running. c = 1. 2021-10-14T20:09:16.317995Z
Task running. c = 2. 2021-10-14T20:09:21.321536Z
Task running. c = 3. 2021-10-14T20:09:26.318642Z
Task running. c = 4. 2021-10-14T20:09:31.318320Z
THROWING EXCEPTION at 2021-10-14T20:09:36.321458Z
Main thread done sleeping. 2021-10-14T20:10:16.320430Z
Notice:
The exception is silently swallowed by the scheduled executor service.
A work stoppage occurs. No further executions of our task are scheduled. Again, a silent problem.
So when your task throws an exception, you get the worst outcome possible: Silent work stoppage with no explanation.
The solution, as mentioned above: Always use a try-catch within your run method.
† Or perhaps Throwable instead of Exception to catch Error objects too.
You should use the ScheduledFuture object returned by your scheduler.scheduleWithFixedDelay(...) like so :
ScheduledExecutorService scheduler = Executors.newSingleThreadScheduledExecutor();
ScheduledFuture<?> handle =
scheduler.scheduleWithFixedDelay(new Runnable() {
public void run() {
throw new RuntimeException("foo");
}
}, 1, 10, TimeUnit.SECONDS);
// Create and Start an exception handler thread
// pass the "handle" object to the thread
// Inside the handler thread do :
....
try {
handle.get();
} catch (ExecutionException e) {
Exception rootException = e.getCause();
}
Old question but the accepted answer doesn't give explanations and provides a poor example and the most upvoted answer is right on some points but finally encourages you to add catch exceptions in every Runnable.run() method.
I disagree because :
it is not neat : not standard for a task to catch its own exceptions.
it is not robust : a new Runnable subclass could forget to perform the exception catch and the failover associated.
it defeats the low coupling promoted by tasks since that couples the tasks to execute with the way of handling the task result.
it mixes responsibilities : that is not the task responsibility to handle the exception or to communicate the exception to the caller. A task is something to execute.
I think that the exception propagation should be performed by the ExecutorService framework and actually it offers that feature.
Besides, trying to be too clever by trying to short-circuiting the ExecutorService way of working is not a good idea either : the framework may evolve and you want to use it in a standard way.
At last, letting the ExecutorService framework to make its job doesn't mean necessarily halting the subsequent invocations task.
If a scheduled task encounters an issue, that is the caller responsibility to re-schedule or not the task according to the issue cause.
Each layer has its its responsibilities. Keeping these make code both clear and maintainable.
ScheduledFuture.get() : the right API to catch exceptions and errors occurred in the task
ScheduledExecutorService.scheduleWithFixedDelay()/scheduleAtFixRate() state in their specification :
If any execution of the task encounters an exception, subsequent
executions are suppressed. Otherwise, the task will only terminate via
cancellation or termination of the executor.
It means that ScheduledFuture.get() doesn't return at each scheduled invocation but that it returns for the last invocation of the task, that is a task cancelation : caused by ScheduledFuture.cancel() or a exception thrown in the task.
So handling the ScheduledFuture return to capture the exception with ScheduledFuture.get() looks right :
try {
future.get();
} catch (InterruptedException e) {
// ... to handle
} catch (ExecutionException e) {
// ... and unwrap the exception OR the error that caused the issue
Throwable cause = e.getCause();
}
Example with the default behavior : halting the scheduling if one of the task execution encounters an issue
It executes a task that for the third executions thrown an exception and terminates the scheduling.
In some scenarios, we want that.
import java.util.concurrent.ExecutionException;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicInteger;
public class ScheduledExecutorServiceWithException {
public static void main(String[] args) {
ScheduledExecutorService executor = Executors.newScheduledThreadPool(2);
// variable used to thrown an error at the 3rd task invocation
AtomicInteger countBeforeError = new AtomicInteger(3);
// boolean allowing to leave the client to halt the scheduling task or not after a failure
Future<?> futureA = executor
.scheduleWithFixedDelay(new MyRunnable(countBeforeError), 1, 2, TimeUnit.SECONDS);
try {
System.out.println("before get()");
futureA.get(); // will return only if canceled
System.out.println("after get()");
} catch (InterruptedException e) {
// handle that : halt or no
} catch (ExecutionException e) {
System.out.println("exception caught :" + e.getCause());
}
// shutdown the executorservice
executor.shutdown();
}
private static class MyRunnable implements Runnable {
private final AtomicInteger invocationDone;
public MyRunnable(AtomicInteger invocationDone) {
this.invocationDone = invocationDone;
}
#Override
public void run() {
System.out.println(Thread.currentThread().getName() + ", execution");
if (invocationDone.decrementAndGet() == 0) {
throw new IllegalArgumentException("ohhh an Exception in MyRunnable");
}
}
}
}
Output :
before get()
pool-1-thread-1, execution
pool-1-thread-1, execution
pool-1-thread-1, execution
exception caught :java.lang.IllegalArgumentException: ohhh an Exception in MyRunnable
Example with the possibility to go on the scheduling if one of the task execution encounters an issue
It executes a task that throws an exception at the two first executions and throws an error at the third one.
We can see that the client of the tasks can choose to halt or not the scheduling : here I go on in cases of exception and I stop in case of error.
import java.util.concurrent.ExecutionException;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicInteger;
public class ScheduledExecutorServiceWithException {
public static void main(String[] args) {
ScheduledExecutorService executor = Executors.newScheduledThreadPool(2);
// variable used to thrown an error at the 3rd task invocation
AtomicInteger countBeforeError = new AtomicInteger(3);
// boolean allowing to leave the client to halt the scheduling task or not after a failure
boolean mustHalt = true;
do {
Future<?> futureA = executor
.scheduleWithFixedDelay(new MyRunnable(countBeforeError), 1, 2, TimeUnit.SECONDS);
try {
futureA.get(); // will return only if canceled
} catch (InterruptedException e) {
// handle that : halt or not halt
} catch (ExecutionException e) {
if (e.getCause() instanceof Error) {
System.out.println("I halt in case of Error");
mustHalt = true;
} else {
System.out.println("I reschedule in case of Exception");
mustHalt = false;
}
}
}
while (!mustHalt);
// shutdown the executorservice
executor.shutdown();
}
private static class MyRunnable implements Runnable {
private final AtomicInteger invocationDone;
public MyRunnable(AtomicInteger invocationDone) {
this.invocationDone = invocationDone;
}
#Override
public void run() {
System.out.println(Thread.currentThread().getName() + ", execution");
if (invocationDone.decrementAndGet() == 0) {
throw new Error("ohhh an Error in MyRunnable");
} else {
throw new IllegalArgumentException("ohhh an Exception in MyRunnable");
}
}
}
}
Output :
pool-1-thread-1, execution
I reschedule in case of Exception
pool-1-thread-1, execution
I reschedule in case of Exception
pool-1-thread-2, execution
I halt in case of Error
I know that this is old question, but if somebody is using delayed CompletableFuture with ScheduledExecutorService then should handle this in that way:
private static CompletableFuture<String> delayed(Duration delay) {
CompletableFuture<String> delayed = new CompletableFuture<>();
executor.schedule(() -> {
String value = null;
try {
value = mayThrowExceptionOrValue();
} catch (Throwable ex) {
delayed.completeExceptionally(ex);
}
if (!delayed.isCompletedExceptionally()) {
delayed.complete(value);
}
}, delay.toMillis(), TimeUnit.MILLISECONDS);
return delayed;
}
and handling exception in CompletableFuture:
CompletableFuture<String> delayed = delayed(Duration.ofSeconds(5));
delayed.exceptionally(ex -> {
//handle exception
return null;
}).thenAccept(value -> {
//handle value
});
Another solution would be to swallow an exception in the Runnable. You can use a convenient VerboseRunnable class from jcabi-log, for example:
import com.jcabi.log.VerboseRunnable;
scheduler.scheduleWithFixedDelay(
new VerboseRunnable(
Runnable() {
public void run() {
// do business logic, may Exception occurs
}
},
true // it means that all exceptions will be swallowed and logged
),
1, 10, TimeUnit.SECONDS
);
Inspired by #MBec solution, I wrote a nice generic wrapper for the ScheduledExecutorService that:
will catch and print any unhandled thrown exception.
will return a Java 8 CompletableFuture instead of a Future.
:)
import java.util.List;
import java.util.concurrent.Callable;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;
/**
* This class use as a wrapper for the Native Java ScheduledExecutorService class.
* It was created in order to address the very unpleasant scenario of silent death!
* explanation: each time an unhandled exception get thrown from a running task that runs by ScheduledExecutorService
* the thread will die and the exception will die with it (nothing will propagate back to the main thread).
*
* However, HonestScheduledExecutorService will gracefully print the thrown exception with a custom/default message,
* and will also return a Java 8 compliant CompletableFuture for your convenience :)
*/
#Slf4j
public class HonestScheduledExecutorService {
private final ScheduledExecutorService scheduledExecutorService;
private static final String DEFAULT_FAILURE_MSG = "Failure occurred when running scheduled task.";
HonestScheduledExecutorService(ScheduledExecutorService scheduledExecutorService) {
this.scheduledExecutorService = scheduledExecutorService;
}
public CompletableFuture<Object> scheduleWithFixedDelay(Callable callable, String onFailureMsg, long initialDelay, long delay, TimeUnit unit) {
final String msg = StringUtils.isEmpty(onFailureMsg) ? DEFAULT_FAILURE_MSG : onFailureMsg;
CompletableFuture<Object> delayed = new CompletableFuture<>();
scheduledExecutorService.scheduleWithFixedDelay(() -> {
try {
Object result = callable.call();
delayed.complete(result);
} catch (Throwable th) {
log.error(msg, th);
delayed.completeExceptionally(th);
}
}, initialDelay, delay, unit);
return delayed;
}
public CompletableFuture<Void> scheduleWithFixedDelay(Runnable runnable, String onFailureMsg, long initialDelay, long delay, TimeUnit unit) {
final String msg = StringUtils.isEmpty(onFailureMsg) ? DEFAULT_FAILURE_MSG : onFailureMsg;
CompletableFuture<Void> delayed = new CompletableFuture<>();
scheduledExecutorService.scheduleWithFixedDelay(() -> {
try {
runnable.run();
delayed.complete(null);
} catch (Throwable th) {
log.error(msg, th);
delayed.completeExceptionally(th);
}
}, initialDelay, delay, unit);
return delayed;
}
public CompletableFuture<Object> schedule(Callable callable, String failureMsg, long delay, TimeUnit unit) {
final String msg = StringUtils.isEmpty(failureMsg) ? DEFAULT_FAILURE_MSG : failureMsg;
CompletableFuture<Object> delayed = new CompletableFuture<>();
scheduledExecutorService.schedule(() -> {
try {
Object result = callable.call();
delayed.complete(result);
} catch (Throwable th) {
log.error(msg, th);
delayed.completeExceptionally(th);
}
}, delay, unit);
return delayed;
}
public CompletableFuture<Void> schedule(Runnable runnable, String failureMsg, long delay, TimeUnit unit) {
final String msg = StringUtils.isEmpty(failureMsg) ? DEFAULT_FAILURE_MSG : failureMsg;
CompletableFuture<Void> delayed = new CompletableFuture<>();
scheduledExecutorService.schedule(() -> {
try {
runnable.run();
delayed.complete(null);
} catch (Throwable th) {
log.error(msg, th);
delayed.completeExceptionally(th);
}
}, delay, unit);
return delayed;
}
public CompletableFuture<Object> scheduleAtFixedRate(Callable callable, String failureMsg, long initialDelay, long period, TimeUnit unit) {
final String msg = StringUtils.isEmpty(failureMsg) ? DEFAULT_FAILURE_MSG : failureMsg;
CompletableFuture<Object> delayed = new CompletableFuture<>();
scheduledExecutorService.scheduleAtFixedRate(() -> {
try {
Object result = callable.call();
delayed.complete(result);
} catch (Throwable th) {
log.error(msg, th);
delayed.completeExceptionally(th);
}
}, initialDelay, period, unit);
return delayed;
}
public CompletableFuture<Void> scheduleAtFixedRate(Runnable runnable, String failureMsg, long initialDelay, long period, TimeUnit unit) {
final String msg = StringUtils.isEmpty(failureMsg) ? DEFAULT_FAILURE_MSG : failureMsg;
CompletableFuture<Void> delayed = new CompletableFuture<>();
scheduledExecutorService.scheduleAtFixedRate(() -> {
try {
runnable.run();
delayed.complete(null);
} catch (Throwable th) {
log.error(msg, th);
delayed.completeExceptionally(th);
}
}, initialDelay, period, unit);
return delayed;
}
public CompletableFuture<Object> execute(Callable callable, String failureMsg) {
final String msg = StringUtils.isEmpty(failureMsg) ? DEFAULT_FAILURE_MSG : failureMsg;
CompletableFuture<Object> delayed = new CompletableFuture<>();
scheduledExecutorService.execute(() -> {
try {
Object result = callable.call();
delayed.complete(result);
} catch (Throwable th) {
log.error(msg, th);
delayed.completeExceptionally(th);
}
});
return delayed;
}
public CompletableFuture<Void> execute(Runnable runnable, String failureMsg) {
final String msg = StringUtils.isEmpty(failureMsg) ? DEFAULT_FAILURE_MSG : failureMsg;
CompletableFuture<Void> delayed = new CompletableFuture<>();
scheduledExecutorService.execute(() -> {
try {
runnable.run();
delayed.complete(null);
} catch (Throwable th) {
log.error(msg, th);
delayed.completeExceptionally(th);
}
});
return delayed;
}
public boolean awaitTermination(long timeout, TimeUnit unit) throws InterruptedException {
return scheduledExecutorService.awaitTermination(timeout, unit);
}
public List<Runnable> shutdownNow() {
return scheduledExecutorService.shutdownNow();
}
public void shutdown() {
scheduledExecutorService.shutdown();
}
}
An elegent way to catch the exception and keep scheduled tasks alive.
First, define a functional interface.
#FunctionalInterface
interface NoSuppressedRunnable extends Runnable {
#Override
default void run() {
try {
doRun();
} catch (Exception e) {
log.error("...", e);
}
}
void doRun();
}
Then, commit the job like this.
executorService.scheduleAtFixedRate((NoSuppressedRunnable) () -> {
// Complier implies that this is an implement of doRun() once you put the cast above
}, 0, 60L, TimeUnit.SECONDS);
Any exception in the run() of a thread which is passed to (ScheduledExecutorService) is never thrown out and if we use future.get() to get status, then the main thread waits infinitely
Personally, I disagree with all the answers here. The main issue with all of them is they provide the same solution in weird flavors. Instead, what you should be doing is creating your own thread factory that installs an uncaught exception handler on the thread that is being created. For example, this is the DefaultThreadFactory that is installed into any executor that would create threads on its own. Shamefully, it's still a private class as of Java 11, since I would like to extend it instead of copying it into my codebase. Below is a snippet how it appears in Executors.java file.
private static class DefaultThreadFactory implements ThreadFactory {
private static final AtomicInteger poolNumber = new AtomicInteger(1);
private final ThreadGroup group;
private final AtomicInteger threadNumber = new AtomicInteger(1);
private final String namePrefix;
DefaultThreadFactory() {
SecurityManager s = System.getSecurityManager();
group = (s != null) ? s.getThreadGroup() :
Thread.currentThread().getThreadGroup();
namePrefix = "pool-" +
poolNumber.getAndIncrement() +
"-thread-";
}
public Thread newThread(Runnable r) {
Thread t = new Thread(group, r,
namePrefix + threadNumber.getAndIncrement(),
0);
if (t.isDaemon())
t.setDaemon(false);
if (t.getPriority() != Thread.NORM_PRIORITY)
t.setPriority(Thread.NORM_PRIORITY);
return t;
}
}
As you can see, the interface itself is a single method that handles creating new threads. There isn't much magic to it besides figuring out the thread group where is the thread factory created in. The interesting bit is that threads are created as non-daemon.
When the thread is created, you can call setThreadUncaughtExceptionHandler which accepts a handler where you should be handling any uncaught exceptions that had happened in that thread. By default, it will be inherited from your thread group, which has the following
public void uncaughtException(Thread t, Throwable e) {
if (parent != null) {
parent.uncaughtException(t, e);
} else {
Thread.UncaughtExceptionHandler ueh =
Thread.getDefaultUncaughtExceptionHandler();
if (ueh != null) {
ueh.uncaughtException(t, e);
} else if (!(e instanceof ThreadDeath)) {
System.err.print("Exception in thread \""
+ t.getName() + "\" ");
e.printStackTrace(System.err);
}
}
}
By default, it will attempt to delegate handling to parent thread group if it exists, and only then test for platform default uncaught exception handler. Usually it is not explicitly installed. If you want to do some real damage to poor codebases that are not aware of this, you can install one via Thread#setDefaultUncaughtExceptionHandler. Don't worry, you won't get to do that if the runtime has Security manager in place.
If you were to install your own handler, that handler will be called instead of the group one.
Now with that out of the way, to your question: How do you handle exceptions in Executors. By default, a thread is considered dead if code is unable to handle its own errors. And I think you should adhere to that. Uncaught exception handler won't save your thread. Instead it will help you diagnose what happened. To segway into ScheduledExecutor implementations, which permit periodic execution of a runnable, the same rules apply: if one execution fails, the thread is killed, along with the runnable that was supposed to get run.
In short, handle your own errors. We have checked exceptions for a reason.
But what about unchecked exceptions?
Funny, since I will commit the same sin as other posters do: use try/catch on Throwable, but assert that it's not a ThreadDeath error. If you do get one, you must rethrow it to ensure the thread actually does die.

How do I call some blocking method with a timeout in Java?

Is there a standard nice way to call a blocking method with a timeout in Java? I want to be able to do:
// call something.blockingMethod();
// if it hasn't come back within 2 seconds, forget it
if that makes sense.
Thanks.
You could use an Executor:
ExecutorService executor = Executors.newCachedThreadPool();
Callable<Object> task = new Callable<Object>() {
public Object call() {
return something.blockingMethod();
}
};
Future<Object> future = executor.submit(task);
try {
Object result = future.get(5, TimeUnit.SECONDS);
} catch (TimeoutException ex) {
// handle the timeout
} catch (InterruptedException e) {
// handle the interrupts
} catch (ExecutionException e) {
// handle other exceptions
} finally {
future.cancel(true); // may or may not desire this
}
If the future.get doesn't return in 5 seconds, it throws a TimeoutException. The timeout can be configured in seconds, minutes, milliseconds or any unit available as a constant in TimeUnit.
See the JavaDoc for more detail.
You could wrap the call in a FutureTask and use the timeout version of get().
See http://java.sun.com/j2se/1.5.0/docs/api/java/util/concurrent/FutureTask.html
See also Guava's TimeLimiter which uses an Executor behind the scenes.
It's really great that people try to implement this in so many ways. But the truth is, there is NO way.
Most developers would try to put the blocking call in a different thread and have a future or some timer. BUT there is no way in Java to stop a thread externally, let alone a few very specific cases like the Thread.sleep() and Lock.lockInterruptibly() methods that explicitly handle thread interruption.
So really you have only 3 generic options:
Put your blocking call on a new thread and if the time expires you just move on, leaving that thread hanging. In that case you should make sure the thread is set to be a Daemon thread. This way the thread will not stop your application from terminating.
Use non blocking Java APIs. So for network for example, use NIO2 and use the non blocking methods. For reading from the console use Scanner.hasNext() before blocking etc.
If your blocking call is not an IO, but your logic, then you can repeatedly check for Thread.isInterrupted() to check if it was interrupted externally, and have another thread call thread.interrupt() on the blocking thread
This course about concurrency https://www.udemy.com/java-multithreading-concurrency-performance-optimization/?couponCode=CONCURRENCY
really walks through those fundamentals if you really want to understand how it works in Java. It actually talks about those specific limitations and scenarios, and how to go about them in one of the lectures.
I personally try to program without using blocking calls as much as possible. There are toolkits like Vert.x for example that make it really easy and performant to do IO and no IO operations asynchronously and in a non blocking way.
I hope it helps
There is also an AspectJ solution for that with jcabi-aspects library.
#Timeable(limit = 30, unit = TimeUnit.MINUTES)
public Soup cookSoup() {
// Cook soup, but for no more than 30 minutes (throw and exception if it takes any longer
}
It can't get more succinct, but you have to depend on AspectJ and introduce it in your build lifecycle, of course.
There is an article explaining it further: Limit Java Method Execution Time
I'm giving you here the complete code. In place of the method I'm calling, you can use your method:
public class NewTimeout {
public String simpleMethod() {
return "simple method";
}
public static void main(String[] args) {
ExecutorService executor = Executors.newSingleThreadScheduledExecutor();
Callable<Object> task = new Callable<Object>() {
public Object call() throws InterruptedException {
Thread.sleep(1100);
return new NewTimeout().simpleMethod();
}
};
Future<Object> future = executor.submit(task);
try {
Object result = future.get(1, TimeUnit.SECONDS);
System.out.println(result);
} catch (TimeoutException ex) {
System.out.println("Timeout............Timeout...........");
} catch (InterruptedException e) {
// handle the interrupts
} catch (ExecutionException e) {
// handle other exceptions
} finally {
executor.shutdown(); // may or may not desire this
}
}
}
Thread thread = new Thread(new Runnable() {
public void run() {
something.blockingMethod();
}
});
thread.start();
thread.join(2000);
if (thread.isAlive()) {
thread.stop();
}
Note, that stop is deprecated, better alternative is to set some volatile boolean flag, inside blockingMethod() check it and exit, like this:
import org.junit.*;
import java.util.*;
import junit.framework.TestCase;
public class ThreadTest extends TestCase {
static class Something implements Runnable {
private volatile boolean stopRequested;
private final int steps;
private final long waitPerStep;
public Something(int steps, long waitPerStep) {
this.steps = steps;
this.waitPerStep = waitPerStep;
}
#Override
public void run() {
blockingMethod();
}
public void blockingMethod() {
try {
for (int i = 0; i < steps && !stopRequested; i++) {
doALittleBit();
}
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
}
public void doALittleBit() throws InterruptedException {
Thread.sleep(waitPerStep);
}
public void setStopRequested(boolean stopRequested) {
this.stopRequested = stopRequested;
}
}
#Test
public void test() throws InterruptedException {
final Something somethingRunnable = new Something(5, 1000);
Thread thread = new Thread(somethingRunnable);
thread.start();
thread.join(2000);
if (thread.isAlive()) {
somethingRunnable.setStopRequested(true);
thread.join(2000);
assertFalse(thread.isAlive());
} else {
fail("Exptected to be alive (5 * 1000 > 2000)");
}
}
}
You need a circuit breaker implementation like the one present in the failsafe project on GitHub.
Try this. More simple solution. Guarantees that if block didn't execute within the time limit. the process will terminate and throws an exception.
public class TimeoutBlock {
private final long timeoutMilliSeconds;
private long timeoutInteval=100;
public TimeoutBlock(long timeoutMilliSeconds){
this.timeoutMilliSeconds=timeoutMilliSeconds;
}
public void addBlock(Runnable runnable) throws Throwable{
long collectIntervals=0;
Thread timeoutWorker=new Thread(runnable);
timeoutWorker.start();
do{
if(collectIntervals>=this.timeoutMilliSeconds){
timeoutWorker.stop();
throw new Exception("<<<<<<<<<<****>>>>>>>>>>> Timeout Block Execution Time Exceeded In "+timeoutMilliSeconds+" Milli Seconds. Thread Block Terminated.");
}
collectIntervals+=timeoutInteval;
Thread.sleep(timeoutInteval);
}while(timeoutWorker.isAlive());
System.out.println("<<<<<<<<<<####>>>>>>>>>>> Timeout Block Executed Within "+collectIntervals+" Milli Seconds.");
}
/**
* #return the timeoutInteval
*/
public long getTimeoutInteval() {
return timeoutInteval;
}
/**
* #param timeoutInteval the timeoutInteval to set
*/
public void setTimeoutInteval(long timeoutInteval) {
this.timeoutInteval = timeoutInteval;
}
}
example :
try {
TimeoutBlock timeoutBlock = new TimeoutBlock(10 * 60 * 1000);//set timeout in milliseconds
Runnable block=new Runnable() {
#Override
public void run() {
//TO DO write block of code
}
};
timeoutBlock.addBlock(block);// execute the runnable block
} catch (Throwable e) {
//catch the exception here . Which is block didn't execute within the time limit
}
In special case of a blocking queue:
Generic java.util.concurrent.SynchronousQueue has a poll method with timeout parameter.
Assume blockingMethod just sleep for some millis:
public void blockingMethod(Object input) {
try {
Thread.sleep(3000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
My solution is to use wait() and synchronized like this:
public void blockingMethod(final Object input, long millis) {
final Object lock = new Object();
new Thread(new Runnable() {
#Override
public void run() {
blockingMethod(input);
synchronized (lock) {
lock.notify();
}
}
}).start();
synchronized (lock) {
try {
// Wait for specific millis and release the lock.
// If blockingMethod is done during waiting time, it will wake
// me up and give me the lock, and I will finish directly.
// Otherwise, when the waiting time is over and the
// blockingMethod is still
// running, I will reacquire the lock and finish.
lock.wait(millis);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
So u can replace
something.blockingMethod(input)
to
something.blockingMethod(input, 2000)
Hope it helps.

Categories