I'm working on a software development framework for parallel computing JavaSeis.org. I need a robust mechanism for reporting thread exceptions. During development, knowing where exceptions came from has high value, so I would like to err on the side of over-reporting. I would also like to be able to handle Junit4 testing in threads as well. Is the approach below reasonable or is there a better way ?
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
public class TestThreadFailure {
public static void main(String[] args) {
int size = 1;
ExecutorService exec = Executors.newFixedThreadPool(size);
ThreadFailTask worker = new ThreadFailTask();
Future<Integer> result = exec.submit(worker);
try {
Integer value = result.get();
System.out.println("Result: " + value);
} catch (Throwable t) {
System.out.println("Caught failure: " + t.toString());
exec.shutdownNow();
System.out.println("Stack Trace:");
t.printStackTrace();
return;
}
throw new RuntimeException("Did not catch failure !!");
}
public static class ThreadFailTask implements Callable<Integer> {
#Override
public Integer call() {
int nbuf = 65536;
double[][] buf = new double[nbuf][nbuf];
return new Integer((int) buf[0][0]);
}
}
}
Consider calling execute() instead of submit() on the ExecutorService. A Thread invoked with execute() will invoke the Thread.UncaughtExceptionHandler when it fails.
Simply make a ThreadFactory that installs a Thread.UncaughtExceptionHandler on all Threads and then invoke your work with execute() on the ExecutorService instead of submit().
Have a look at this related stack overflow question.
I don't believe there is a standard 'hook' to get to these exceptions when using submit(). However, if you need to support submit() (which sounds reasonable, given that you use a Callable), you can always wrap the Callables and Runnables :
ExecutorService executor = new ThreadPoolExecutor(1, 10, 60, TimeUnit.SECONDS, new LinkedBlockingDeque<Runnable>()) {
#Override
public <T> Future<T> submit(final Callable<T> task) {
Callable<T> wrappedTask = new Callable<T>() {
#Override
public T call() throws Exception {
try {
return task.call();
}
catch (Exception e) {
System.out.println("Oh boy, something broke!");
e.printStackTrace();
throw e;
}
}
};
return super.submit(wrappedTask);
}
};
Of course, this method only works if you're the one building the ExecutorService in the first place. Furthermore, remember to override all three submit() variants.
As explained in this thread What is the difference between submit and execute method with ThreadPoolExecutor, using execute will only work if you implement Runnable and not Callable as execute cannot return a Future.
I think in your scenario you should build the future object so that it can accommodate the exception stuff also. So in case of exception you build the error message object.
My original question asked how to implement "robust" thread exception handling with Java ExecutorService. Thanks to Angelo and Greg for pointers on how exception handling works with ExecutorService.submit() and Future.get(). My revised code fragment is shown below. The key point I learned here is that Future.get() catches all exceptions. If the the thread was interrupted or cancelled, you get the appropriate exception, otherwise, the exception is wrapped and re-thrown as an ExecutionException.
import java.util.concurrent.Callable;
import java.util.concurrent.CancellationException;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
public class TestThreadFailure {
public static void main(String[] args) {
int size = 1;
ExecutorService exec = Executors.newFixedThreadPool(size);
ThreadFailTask worker = new ThreadFailTask();
Future result = exec.submit(worker);
try {
Integer value = result.get();
System.out.println("Result: " + value);
} catch (ExecutionException ex) {
System.out.println("Caught failure: " + ex.toString());
exec.shutdownNow();
return;
} catch (InterruptedException iex) {
System.out.println("Thread interrupted: " + iex.toString());
} catch (CancellationException cex) {
System.out.println("Thread cancelled: " + cex.toString());
}
exec.shutdownNow();
throw new RuntimeException("Did not catch failure !!");
}
public static class ThreadFailTask implements Callable {
#Override
public Integer call() {
int nbuf = 65536;
double[][] buf = new double[nbuf][nbuf];
return new Integer((int) buf[0][0]);
}
}
}
I didn't have a great deal of luck with other answers because I needed the actual exception instance, itself, not just a printed stack trace. For me, the accepted answer involving ThreadPoolExecutor#afterExecute() of the question "Why is UncaughtExceptionHandler not called by ExecutorService?" worked.
See the following sample code:
List<Runnable> tasks = new LinkedList<>();
for (int i = 0; i < numThreads; ++i) {
Runnable task = new Runnable() {
#Override
public void run() {
throw new RuntimeException();
}
};
tasks.add(task);
}
Optional<Throwable> opEmpty = Optional.empty();
/*
* Use AtomicReference as a means of capturing the first thrown exception, since a
* spawned thread can't "throw" an exception to the parent thread.
*/
final AtomicReference<Optional<Throwable>> firstThrownException =
new AtomicReference<>(opEmpty);
/*
* Use new ThreadPoolExecutor instead of Executors.newFixedThreadPool() so
* that I can override afterExecute() for the purposes of throwing an
* exception from the test thread if a child thread fails.
*/
ExecutorService execSvc = new ThreadPoolExecutor(numThreads, numThreads,
0L, TimeUnit.MILLISECONDS, new LinkedBlockingQueue<Runnable>()) {
#Override
public void afterExecute(Runnable task, Throwable failureCause) {
if(failureCause == null) {
// The Runnable completed successfully.
return;
}
// only sets the first exception because it will only be empty on the first call.
firstThrownException.compareAndSet(Optional.<Throwable>empty(), Optional.of(failureCause));
}
};
for (Runnable task : tasks) {
execSvc.execute(task);
}
execSvc.shutdown();
execSvc.awaitTermination(1, TimeUnit.HOURS);
assertEquals(firstThrownException.get(), Optional.empty());
To Handling exceptions in ExecutorService you have to take the advantage of Callable and Future.
Callable is similar to Runnable and both are functional interface but run() of Runnable doesn't throws exception and the return type is void where as call() of Callable returns a generics and throws exception.
Java-8 way:
ExecuterService executor = null;
Future<Integer> future = null;
Callable<Integer> yourTask = () -> {
//your implementation here();
//your implementation here();
};
try
{
executor = Executors.newCachedThreadPool();
future = executor.submit(yourTask );
Integer result = future.get();
System.out.println(result);
}
catch (ExecutionException | TimeoutException | InterruptedException e)
{
// TODO: handle exception
}
finally
{
executer.shutdown();
}
Related
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.
I'm trying to build something like a background task executor which terminates background tasks after a certain time if there's no answer (background tasks call webservices and they can time-out but I need to make sure they time out under a certain time)
So I have this as an experiment but if I run this the program does not terminate. I wonder if its because a background thread is still active maybe? How can I shut this down?
public class Test {
public static class Task implements Callable<Object> {
#Override
public Object call() throws Exception {
while(true) {}
}
}
public static void main(String[] args) {
try {
Task t = new Task();
ExecutorService executor = Executors.newSingleThreadExecutor();
executor.invokeAll(Arrays.asList(t), 5L, TimeUnit.SECONDS);
executor.shutdown();
System.out.println("DONE");
}
catch (InterruptedException e) {
e.printStackTrace();
}
}
}
The ExecutorService does not kill the running threads, and since threads are created as non-daemon, the JVM doesn't exit.
What happens is that when timeout expires, futures returned by invokeAll() are cancelled, which means that a flag is set on the future object and you get a CancellationException if you try to call future.get(). However neither invokeAll(), nor shutdown() (or shutdownNow()) do anything to kill the thread.
Note that you cannot even kill threads yourself. All you can do is setting some application-specific flag or call Thread.interrupt(), but even that does not guarantee that the thread terminates.
There is a great post by Winterbe on how executors work. This is an excerpt from his tutorial
So basically executors always keep listening to the new tasks or callables/runnables and one way to shutdown the executor or stop the executor from listening is to interrupt whatever task it is executing. One way to do is calling the future.get() which stops when the main thread , suspends it and makes sure that the current thread gets executed completely before handing over the resource to other thread
You could probably have a higher number of threads and write your code to shutdown gracefully in the InterruptedException block
Here is a sample code that I've written and tested:
import java.util.Arrays;
import java.util.List;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;
public class ExecutorTest {
public static void main(String[] args) {
ExecutorService service = Executors.newWorkStealingPool(10);
Callable<AccountClass> newInstance = () -> {
TimeUnit.SECONDS.sleep(3);
return getAcc(Thread.currentThread().getId());
};
// for now only one instance is added to the list
// List<Callable<AccountClass>> callablesSingleList = Arrays.asList(newInstance);
// adding multipleCallalbes
List<Callable<AccountClass>> callablesMultipleList = Arrays.asList(
() -> {
TimeUnit.SECONDS.sleep(3);
return getAcc(Thread.currentThread().getId());
},
() -> {
TimeUnit.SECONDS.sleep(3);
return getAcc(Thread.currentThread().getId());
},
() -> {
TimeUnit.SECONDS.sleep(3);
return getAcc(Thread.currentThread().getId());
});
try {
service.invokeAll(callablesMultipleList).stream().map(future -> {
AccountClass fuClass = null;
try {
fuClass = future.get();
} catch (InterruptedException e) {
e.printStackTrace();
} catch (ExecutionException e) {
e.printStackTrace();
}
return fuClass;
}).forEach(getValue -> {
System.out.println("retunred value:" + getValue);
});
} catch (InterruptedException ex) {
ex.printStackTrace();
}
}
private static AccountClass getAcc(long itr) {
// probably call DB for every new thread iterator
System.out.println("getting the current thread" + itr);
AccountClass ac = new AccountClass();
ac.setId(itr);
ac.setName("vv");
ac.setRole("admin");
System.out.println("sending the accnt class:" + ac);
return ac;
}
}
UPDATE:
Another way of shutting down the executor is using the service.shutDownNow() - > which shutdowns the program even if its the middle of execution. You could use awaitTermination method to specify if you feel that it might take a few minutes to complete execution and then probably shutdown the service
import java.util.List;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;
public class ExecutorScheduleFixedRate {
public static void main(String[] args) {
ScheduledExecutorService service = Executors.newScheduledThreadPool(10);
Runnable task = () -> {
getAcc(33);
};
service.scheduleWithFixedDelay(task, 10, 5, TimeUnit.SECONDS);
if (!service.isShutdown()) {
List<Runnable> list2 = service.shutdownNow();
System.out.println(list2);
System.out.println("is shutdonw" + service.isShutdown());
System.out.println("Do something after the thread execution");
}
}
private static AccountClass getAcc(long itr) {
// probably call DB for every new thread iterator
System.out.println("getting the current thread" + itr);
AccountClass ac = new AccountClass();
ac.setId(itr);
ac.setName("vv");
ac.setRole("admin");
System.out.println("sending the accnt class:" + ac);
return ac;
}
}
I want to interrupt a thread after a fixed amount of time. Someone else asked the same question, and the top-voted answer (https://stackoverflow.com/a/2275596/1310503) gave the solution below, which I have slightly shortened.
import java.util.Arrays;
import java.util.concurrent.*;
public class Test {
public static void main(String[] args) throws Exception {
ExecutorService executor = Executors.newSingleThreadExecutor();
executor.invokeAll(Arrays.asList(new Task()), 2, TimeUnit.SECONDS);
executor.shutdown();
}
}
class Task implements Callable<String> {
public String call() throws Exception {
try {
System.out.println("Started..");
Thread.sleep(4000); // Just to demo a long running task of 4 seconds.
System.out.println("Finished!");
} catch (InterruptedException e) {
System.out.println("Terminated!");
}
return null;
}
}
They added:
the sleep() is not required. It is just used for SSCCE/demonstration purposes. Just do your long running task right there in place of sleep().
But if you replace Thread.sleep(4000); with for (int i = 0; i < 5E8; i++) {} then it doesn't compile, because the empty loop doesn't throw an InterruptedException. And for the thread to be interruptible, it needs to throw an InterruptedException.
Is there any way of making the above code work with a general long-running task instead of sleep()?
If you want you action to be interruptable (i.e. it should be possible to interrupt it before it's completed) you need to either use other interruptable action (Thread.sleep, InputStream.read, read for more info) or manually check thread interruption status in your cycle condition using Thread.isInterrupted.
You could check the interrupted status of the thread, for example:
public static void main(String[] args) throws Exception {
ExecutorService executor = Executors.newSingleThreadExecutor();
executor.invokeAll(Arrays.asList(new Task()), 2, TimeUnit.SECONDS);
executor.shutdown();
}
static class Task implements Callable<String> {
public String call() throws Exception {
System.out.println("Started..");
for (int i = 0; i < Integer.MAX_VALUE; i++) {
if (Thread.currentThread().isInterrupted()) {
System.out.println("Interrupted!");
return null;
}
}
System.out.println("Finished!");
return null;
}
}
You've misunderstood.
"...for the thread to be interruptible, it needs to throw an InterruptedException" is simply not true. That catch block is there only because the Thread.sleep() method throws InterruptedException. If you're not using sleep (or any other code which can throw InterruptedException), then you don't need the catch block.
None of the code will throw InterruptedException if you replace the sleep.
You should remove the try-catch for InterruptedException:
public String call() {
System.out.println("Started..");
for (int i = 0; i < 5E8; i++) {}
System.out.println("Finished!");
return null;
}
It boils down to one thread submitting job via some service. Job is executed in some TPExecutor. Afterwards this service checks for results and throw exception in original thread under certain conditions (job exceeds maximum number of retries, etc.). Code snippet below roughly illustrate this scenario in legacy code:
import java.util.concurrent.CountDownLatch;
public class IncorrectLockingExample {
private static class Request {
private final CountDownLatch latch = new CountDownLatch(1);
private Throwable throwable;
public void await() {
try {
latch.await();
} catch (InterruptedException ignoredForDemoPurposes) {
}
}
public void countDown() {
latch.countDown();
}
public Throwable getThrowable() {
return throwable;
}
public void setThrowable(Throwable throwable) {
this.throwable = throwable;
}
}
private static final Request wrapper = new Request();
public static void main(String[] args) throws InterruptedException {
final Thread blockedThread = new Thread() {
public void run() {
wrapper.await();
synchronized (wrapper) {
if (wrapper.getThrowable() != null)
throw new RuntimeException(wrapper.getThrowable());
}
}
};
final Thread workingThread = new Thread() {
public void run() {
wrapper.setThrowable(new RuntimeException());
wrapper.countDown();
}
};
blockedThread.start();
workingThread.start();
blockedThread.join();
workingThread.join();
}
}
Sometimes, (not reproducible on my box, but happens on 16 core server box) exception isn't getting reported to original thread. I think this is because happens-before is not forced(eg. 'countDown' happens before 'setThrowable') and program continues to work(but should fail).
I would appreciate any help about how to resolve this case.
Constraints are: release in a week, minimum impact on existing codebase is needed.
The code above (as now updated) should work as you expected without the use of further synchronisation mechanisms. The memory barrier and its corresponding 'happens-before' relationship is enforced by the use of the CountDownLatch await() and countdown() methods.
From the API docs:
Actions prior to "releasing" synchronizer methods such as Lock.unlock, Semaphore.release, and CountDownLatch.countDown happen-before actions subsequent to a successful "acquiring" method such as Lock.lock, Semaphore.acquire, Condition.await, and CountDownLatch.await on the same synchronizer object in another thread.
If you are dealing with concurrency on a regular basis get yourself a copy of 'Java Concurrency in Practice', it's the Java concurrency bible and will be well worth its weight on your bookshelf :-).
I suspect you need
private volatile Throwable throwable
Have you tried using an ExecutorService as it is built in and does this for you. The following prints
future1 := result
future2 threw java.lang.IllegalStateException
future3 timed out
The code is
public static void main(String... args) {
ExecutorService executor = Executors.newSingleThreadExecutor();
Future<String> future1 = executor.submit(new Callable<String>() {
public String call() throws Exception {
return "result";
}
});
Future<String> future2 = executor.submit(new Callable<String>() {
public String call() throws Exception {
throw new IllegalStateException();
}
});
Future<String> future3 = executor.submit(new Callable<String>() {
public String call() throws Exception {
Thread.sleep(2000);
throw new AssertionError();
}
});
printResult("future1", future1);
printResult("future2", future2);
printResult("future3", future3);
executor.shutdown();
}
private static void printResult(String description, Future<String> future) {
try {
System.out.println(description+" := "+future.get(1, TimeUnit.SECONDS));
} catch (InterruptedException e) {
System.out.println(description+" interrupted");
} catch (ExecutionException e) {
System.out.println(description+" threw "+e.getCause());
} catch (TimeoutException e) {
System.out.println(description+" timed out");
}
}
In the code for FutureTask, there is a comment.
/**
* The thread running task. When nulled after set/cancel, this
* indicates that the results are accessible. Must be
* volatile, to ensure visibility upon completion.
*/
If you are not going to re-use the code in the JDK, it can still be worth reading it so you can pick up on any tricks they use.
I want to run a thread for some fixed amount of time. If it is not completed within that time, I want to either kill it, throw some exception, or handle it in some way. How can it be done?
One way of doing it as I figured out from this thread
is to use a TimerTask inside the run() method of the Thread.
Are there any better solutions for this?
EDIT: Adding a bounty as I needed a clearer answer. The ExecutorService code given below does not address my problem. Why should I sleep() after executing (some code - I have no handle over this piece of code)? If the code is completed and the sleep() is interrupted, how can that be a timeOut?
The task that needs to be executed is not in my control. It can be any piece of code. The problem is this piece of code might run into an infinite loop. I don't want that to happen. So, I just want to run that task in a separate thread. The parent thread has to wait till that thread finishes and needs to know the status of the task (i.e whether it timed out or some exception occured or if its a success). If the task goes into an infinite loop, my parent thread keeps on waiting indefinitely, which is not an ideal situation.
Indeed rather use ExecutorService instead of Timer, here's an SSCCE:
package com.stackoverflow.q2275443;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;
public class Test {
public static void main(String[] args) throws Exception {
ExecutorService executor = Executors.newSingleThreadExecutor();
Future<String> future = executor.submit(new Task());
try {
System.out.println("Started..");
System.out.println(future.get(3, TimeUnit.SECONDS));
System.out.println("Finished!");
} catch (TimeoutException e) {
future.cancel(true);
System.out.println("Terminated!");
}
executor.shutdownNow();
}
}
class Task implements Callable<String> {
#Override
public String call() throws Exception {
Thread.sleep(4000); // Just to demo a long running task of 4 seconds.
return "Ready!";
}
}
Play a bit with the timeout argument in Future#get() method, e.g. increase it to 5 and you'll see that the thread finishes. You can intercept the timeout in the catch (TimeoutException e) block.
Update: to clarify a conceptual misunderstanding, the sleep() is not required. It is just used for SSCCE/demonstration purposes. Just do your long running task right there in place of sleep(). Inside your long running task, you should be checking if the thread is not interrupted as follows:
while (!Thread.interrupted()) {
// Do your long running task here.
}
There isn't a 100% reliable way to do this for any old task. The task has to be written with this ability in mind.
Core Java libraries like ExecutorService cancel asynchronous tasks with interrupt() calls on the worker thread. So, for example, if the task contains some sort of loop, you should be checking its interrupt status on each iteration. If the task is doing I/O operations, they should be interruptible too—and setting that up can be tricky. In any case, keep in mind that code has to actively check for interrupts; setting an interrupt doesn't necessarily do anything.
Of course, if your task is some simple loop, you can just check the current time at each iteration and give up when a specified timeout has elapsed. A worker thread isn't needed in that case.
Consider using an instance of ExecutorService. Both invokeAll() and invokeAny() methods are available with a timeout parameter.
The current thread will block until the method completes (not sure if this is desirable) either because the task(s) completed normally or the timeout was reached. You can inspect the returned Future(s) to determine what happened.
Assuming the thread code is out of your control:
From the Java documentation mentioned above:
What if a thread doesn't respond to Thread.interrupt?
In some cases, you can use application specific tricks. For example,
if a thread is waiting on a known socket, you can close the socket to
cause the thread to return immediately. Unfortunately, there really
isn't any technique that works in general. It should be noted that in
all situations where a waiting thread doesn't respond to
Thread.interrupt, it wouldn't respond to Thread.stop either. Such
cases include deliberate denial-of-service attacks, and I/O operations
for which thread.stop and thread.interrupt do not work properly.
Bottom Line:
Make sure all threads can be interrupted, or else you need specific knowledge of the thread - like having a flag to set. Maybe you can require that the task be given to you along with the code needed to stop it - define an interface with a stop() method. You can also warn when you failed to stop a task.
BalusC said:
Update: to clarify a conceptual misunderstanding, the sleep() is not required. It is just used for SSCCE/demonstration purposes. Just do your long running task right there in place of sleep().
But if you replace Thread.sleep(4000); with for (int i = 0; i < 5E8; i++) {} then it doesn't compile, because the empty loop doesn't throw an InterruptedException.
And for the thread to be interruptible, it needs to throw an InterruptedException.
This seems like a serious problem to me. I can't see how to adapt this answer to work with a general long-running task.
Edited to add: I reasked this as a new question: [ interrupting a thread after fixed time, does it have to throw InterruptedException? ]
I created a helper class just for this some time ago. Works great:
import java.util.concurrent.BrokenBarrierException;
import java.util.concurrent.CyclicBarrier;
/**
* TimeOut class - used for stopping a thread that is taking too long
* #author Peter Goransson
*
*/
public class TimeOut {
Thread interrupter;
Thread target;
long timeout;
boolean success;
boolean forceStop;
CyclicBarrier barrier;
/**
*
* #param target The Runnable target to be executed
* #param timeout The time in milliseconds before target will be interrupted or stopped
* #param forceStop If true, will Thread.stop() this target instead of just interrupt()
*/
public TimeOut(Runnable target, long timeout, boolean forceStop) {
this.timeout = timeout;
this.forceStop = forceStop;
this.target = new Thread(target);
this.interrupter = new Thread(new Interrupter());
barrier = new CyclicBarrier(2); // There will always be just 2 threads waiting on this barrier
}
public boolean execute() throws InterruptedException {
// Start target and interrupter
target.start();
interrupter.start();
// Wait for target to finish or be interrupted by interrupter
target.join();
interrupter.interrupt(); // stop the interrupter
try {
barrier.await(); // Need to wait on this barrier to make sure status is set
} catch (BrokenBarrierException e) {
// Something horrible happened, assume we failed
success = false;
}
return success; // status is set in the Interrupter inner class
}
private class Interrupter implements Runnable {
Interrupter() {}
public void run() {
try {
Thread.sleep(timeout); // Wait for timeout period and then kill this target
if (forceStop) {
target.stop(); // Need to use stop instead of interrupt since we're trying to kill this thread
}
else {
target.interrupt(); // Gracefully interrupt the waiting thread
}
System.out.println("done");
success = false;
} catch (InterruptedException e) {
success = true;
}
try {
barrier.await(); // Need to wait on this barrier
} catch (InterruptedException e) {
// If the Child and Interrupter finish at the exact same millisecond we'll get here
// In this weird case assume it failed
success = false;
}
catch (BrokenBarrierException e) {
// Something horrible happened, assume we failed
success = false;
}
}
}
}
It is called like this:
long timeout = 10000; // number of milliseconds before timeout
TimeOut t = new TimeOut(new PhotoProcessor(filePath, params), timeout, true);
try {
boolean sucess = t.execute(); // Will return false if this times out
if (!sucess) {
// This thread timed out
}
else {
// This thread ran completely and did not timeout
}
} catch (InterruptedException e) {}
I think you should take a look at proper concurrency handling mechanisms (threads running into infinite loops doesn't sound good per se, btw). Make sure you read a little about the "killing" or "stopping" Threads topic.
What you are describing,sound very much like a "rendezvous", so you may want to take a look at the CyclicBarrier.
There may be other constructs (like using CountDownLatch for example) that can resolve your problem (one thread waiting with a timeout for the latch, the other should count down the latch if it has done it's work, which would release your first thread either after a timeout or when the latch countdown is invoked).
I usually recommend two books in this area: Concurrent Programming in Java and Java Concurrency in Practice.
In the solution given by BalusC, the main thread will stay blocked for the timeout period. If you have a thread pool with more than one thread, you will need the same number of additional thread that will be using Future.get(long timeout,TimeUnit unit) blocking call to wait and close the thread if it exceeds the timeout period.
A generic solution to this problem is to create a ThreadPoolExecutor Decorator that can add the timeout functionality. This Decorator class should create as many threads as ThreadPoolExecutor has, and all these threads should be used only to wait and close the ThreadPoolExecutor.
The generic class should be implemented like below:
import java.util.List;
import java.util.concurrent.*;
public class TimeoutThreadPoolDecorator extends ThreadPoolExecutor {
private final ThreadPoolExecutor commandThreadpool;
private final long timeout;
private final TimeUnit unit;
public TimeoutThreadPoolDecorator(ThreadPoolExecutor threadpool,
long timeout,
TimeUnit unit ){
super( threadpool.getCorePoolSize(),
threadpool.getMaximumPoolSize(),
threadpool.getKeepAliveTime(TimeUnit.MILLISECONDS),
TimeUnit.MILLISECONDS,
threadpool.getQueue());
this.commandThreadpool = threadpool;
this.timeout=timeout;
this.unit=unit;
}
#Override
public void execute(Runnable command) {
super.execute(() -> {
Future<?> future = commandThreadpool.submit(command);
try {
future.get(timeout, unit);
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
} catch (ExecutionException | TimeoutException e) {
throw new RejectedExecutionException(e);
} finally {
future.cancel(true);
}
});
}
#Override
public void setCorePoolSize(int corePoolSize) {
super.setCorePoolSize(corePoolSize);
commandThreadpool.setCorePoolSize(corePoolSize);
}
#Override
public void setThreadFactory(ThreadFactory threadFactory) {
super.setThreadFactory(threadFactory);
commandThreadpool.setThreadFactory(threadFactory);
}
#Override
public void setMaximumPoolSize(int maximumPoolSize) {
super.setMaximumPoolSize(maximumPoolSize);
commandThreadpool.setMaximumPoolSize(maximumPoolSize);
}
#Override
public void setKeepAliveTime(long time, TimeUnit unit) {
super.setKeepAliveTime(time, unit);
commandThreadpool.setKeepAliveTime(time, unit);
}
#Override
public void setRejectedExecutionHandler(RejectedExecutionHandler handler) {
super.setRejectedExecutionHandler(handler);
commandThreadpool.setRejectedExecutionHandler(handler);
}
#Override
public List<Runnable> shutdownNow() {
List<Runnable> taskList = super.shutdownNow();
taskList.addAll(commandThreadpool.shutdownNow());
return taskList;
}
#Override
public void shutdown() {
super.shutdown();
commandThreadpool.shutdown();
}
}
The above decorator can be used as below:
import java.util.concurrent.SynchronousQueue;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
public class Main {
public static void main(String[] args){
long timeout = 2000;
ThreadPoolExecutor threadPool = new ThreadPoolExecutor(3, 10, 0, TimeUnit.MILLISECONDS, new SynchronousQueue<>(true));
threadPool = new TimeoutThreadPoolDecorator( threadPool ,
timeout,
TimeUnit.MILLISECONDS);
threadPool.execute(command(1000));
threadPool.execute(command(1500));
threadPool.execute(command(2100));
threadPool.execute(command(2001));
while(threadPool.getActiveCount()>0);
threadPool.shutdown();
}
private static Runnable command(int i) {
return () -> {
System.out.println("Running Thread:"+Thread.currentThread().getName());
System.out.println("Starting command with sleep:"+i);
try {
Thread.sleep(i);
} catch (InterruptedException e) {
System.out.println("Thread "+Thread.currentThread().getName()+" with sleep of "+i+" is Interrupted!!!");
return;
}
System.out.println("Completing Thread "+Thread.currentThread().getName()+" after sleep of "+i);
};
}
}
I post you a piece of code which show a way how to solve the problem.
As exemple I'm reading a file.
You could use this method for another operation, but you need to implements the kill() method so that the main operation will be interrupted.
hope it helps
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
/**
* Main class
*
* #author el
*
*/
public class Main {
/**
* Thread which perform the task which should be timed out.
*
* #author el
*
*/
public static class MainThread extends Thread {
/**
* For example reading a file. File to read.
*/
final private File fileToRead;
/**
* InputStream from the file.
*/
final private InputStream myInputStream;
/**
* Thread for timeout.
*/
final private TimeOutThread timeOutThread;
/**
* true if the thread has not ended.
*/
boolean isRunning = true;
/**
* true if all tasks where done.
*/
boolean everythingDone = false;
/**
* if every thing could not be done, an {#link Exception} may have
* Happens.
*/
Throwable endedWithException = null;
/**
* Constructor.
*
* #param file
* #throws FileNotFoundException
*/
MainThread(File file) throws FileNotFoundException {
setDaemon(false);
fileToRead = file;
// open the file stream.
myInputStream = new FileInputStream(fileToRead);
// Instantiate the timeout thread.
timeOutThread = new TimeOutThread(10000, this);
}
/**
* Used by the {#link TimeOutThread}.
*/
public void kill() {
if (isRunning) {
isRunning = false;
if (myInputStream != null) {
try {
// close the stream, it may be the problem.
myInputStream.close();
} catch (IOException e) {
// Not interesting
System.out.println(e.toString());
}
}
synchronized (this) {
notify();
}
}
}
/**
* The task which should be timed out.
*/
#Override
public void run() {
timeOutThread.start();
int bytes = 0;
try {
// do something
while (myInputStream.read() >= 0) {
// may block the thread.
myInputStream.read();
bytes++;
// simulate a slow stream.
synchronized (this) {
wait(10);
}
}
everythingDone = true;
} catch (IOException e) {
endedWithException = e;
} catch (InterruptedException e) {
endedWithException = e;
} finally {
timeOutThread.kill();
System.out.println("-->read " + bytes + " bytes.");
isRunning = false;
synchronized (this) {
notifyAll();
}
}
}
}
/**
* Timeout Thread. Kill the main task if necessary.
*
* #author el
*
*/
public static class TimeOutThread extends Thread {
final long timeout;
final MainThread controlledObj;
TimeOutThread(long timeout, MainThread controlledObj) {
setDaemon(true);
this.timeout = timeout;
this.controlledObj = controlledObj;
}
boolean isRunning = true;
/**
* If we done need the {#link TimeOutThread} thread, we may kill it.
*/
public void kill() {
isRunning = false;
synchronized (this) {
notify();
}
}
/**
*
*/
#Override
public void run() {
long deltaT = 0l;
try {
long start = System.currentTimeMillis();
while (isRunning && deltaT < timeout) {
synchronized (this) {
wait(Math.max(100, timeout - deltaT));
}
deltaT = System.currentTimeMillis() - start;
}
} catch (InterruptedException e) {
// If the thread is interrupted,
// you may not want to kill the main thread,
// but probably yes.
} finally {
isRunning = false;
}
controlledObj.kill();
}
}
/**
* Start the main task and wait for the end.
*
* #param args
* #throws FileNotFoundException
*/
public static void main(String[] args) throws FileNotFoundException {
long start = System.currentTimeMillis();
MainThread main = new MainThread(new File(args[0]));
main.start();
try {
while (main.isRunning) {
synchronized (main) {
main.wait(1000);
}
}
long stop = System.currentTimeMillis();
if (main.everythingDone)
System.out.println("all done in " + (stop - start) + " ms.");
else {
System.out.println("could not do everything in "
+ (stop - start) + " ms.");
if (main.endedWithException != null)
main.endedWithException.printStackTrace();
}
} catch (InterruptedException e) {
System.out.println("You've killed me!");
}
}
}
Regards
Here is my really simple to use helper class to run or call piece of Java code :-)
This is based on the excellent answer from BalusC
package com.mycompany.util.concurrent;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;
/**
* Calling {#link Callable#call()} or Running {#link Runnable#run()} code
* with a timeout based on {#link Future#get(long, TimeUnit))}
* #author pascaldalfarra
*
*/
public class CallableHelper
{
private CallableHelper()
{
}
public static final void run(final Runnable runnable, int timeoutInSeconds)
{
run(runnable, null, timeoutInSeconds);
}
public static final void run(final Runnable runnable, Runnable timeoutCallback, int timeoutInSeconds)
{
call(new Callable<Void>()
{
#Override
public Void call() throws Exception
{
runnable.run();
return null;
}
}, timeoutCallback, timeoutInSeconds);
}
public static final <T> T call(final Callable<T> callable, int timeoutInSeconds)
{
return call(callable, null, timeoutInSeconds);
}
public static final <T> T call(final Callable<T> callable, Runnable timeoutCallback, int timeoutInSeconds)
{
ExecutorService executor = Executors.newSingleThreadExecutor();
try
{
Future<T> future = executor.submit(callable);
T result = future.get(timeoutInSeconds, TimeUnit.SECONDS);
System.out.println("CallableHelper - Finished!");
return result;
}
catch (TimeoutException e)
{
System.out.println("CallableHelper - TimeoutException!");
if(timeoutCallback != null)
{
timeoutCallback.run();
}
}
catch (InterruptedException e)
{
e.printStackTrace();
}
catch (ExecutionException e)
{
e.printStackTrace();
}
finally
{
executor.shutdownNow();
executor = null;
}
return null;
}
}
The following snippet will start an operation in a separate thread, then wait for up to 10 seconds for the operation to complete. If the operation does not complete in time, the code will attempt to cancel the operation, then continue on its merry way. Even if the operation cannot be cancelled easily, the parent thread will not wait for the child thread to terminate.
ExecutorService executorService = getExecutorService();
Future<SomeClass> future = executorService.submit(new Callable<SomeClass>() {
public SomeClass call() {
// Perform long-running task, return result. The code should check
// interrupt status regularly, to facilitate cancellation.
}
});
try {
// Real life code should define the timeout as a constant or
// retrieve it from configuration
SomeClass result = future.get(10, TimeUnit.SECONDS);
// Do something with the result
} catch (TimeoutException e) {
future.cancel(true);
// Perform other error handling, e.g. logging, throwing an exception
}
The getExecutorService() method can be implemented in a number of ways. If you do not have any particular requirements, you can simply call Executors.newCachedThreadPool() for thread pooling with no upper limit on the number of threads.
One thing that I've not seen mentioned is that killing threads is generally a Bad Idea. There are techniques for making threaded methods cleanly abortable, but that's different to just killing a thread after a timeout.
The risk with what you're suggesting is that you probably don't know what state the thread will be in when you kill it - so you risk introducing instability. A better solution is to make sure your threaded code either doesn't hang itself, or will respond nicely to an abort request.
Great answer by BalusC's:
but Just to add that the timeout itself does not interrupt the thread itself. even if you are checking with while(!Thread.interrupted()) in your task. if you want to make sure thread is stopped you should also make sure future.cancel() is invoked when timeout exception is catch.
package com.stackoverflow.q2275443;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;
public class Test {
public static void main(String[] args) throws Exception {
ExecutorService executor = Executors.newSingleThreadExecutor();
Future<String> future = executor.submit(new Task());
try {
System.out.println("Started..");
System.out.println(future.get(3, TimeUnit.SECONDS));
System.out.println("Finished!");
} catch (TimeoutException e) {
//Without the below cancel the thread will continue to live
// even though the timeout exception thrown.
future.cancel();
System.out.println("Terminated!");
}
executor.shutdownNow();
}
}
class Task implements Callable<String> {
#Override
public String call() throws Exception {
while(!Thread.currentThread.isInterrupted()){
System.out.println("Im still running baby!!");
}
}
}
I think the answer mainly depends on the task itself.
Is it doing one task over and over again?
Is it necessary that the timeout interrupts a currently running task immediately after it expires?
If the first answer is yes and the second is no, you could keep it as simple as this:
public class Main {
private static final class TimeoutTask extends Thread {
private final long _timeoutMs;
private Runnable _runnable;
private TimeoutTask(long timeoutMs, Runnable runnable) {
_timeoutMs = timeoutMs;
_runnable = runnable;
}
#Override
public void run() {
long start = System.currentTimeMillis();
while (System.currentTimeMillis() < (start + _timeoutMs)) {
_runnable.run();
}
System.out.println("execution took " + (System.currentTimeMillis() - start) +" ms");
}
}
public static void main(String[] args) throws Exception {
new TimeoutTask(2000L, new Runnable() {
#Override
public void run() {
System.out.println("doing something ...");
try {
// pretend it's taking somewhat longer than it really does
Thread.sleep(100);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
}
}).start();
}
}
If this isn't an option, please narrow your requirements - or show some code.
I was looking for an ExecutorService that can interrupt all timed out Runnables executed by it, but found none. After a few hours I created one as below. This class can be modified to enhance robustness.
public class TimedExecutorService extends ThreadPoolExecutor {
long timeout;
public TimedExecutorService(int numThreads, long timeout, TimeUnit unit) {
super(numThreads, numThreads, 0L, TimeUnit.MILLISECONDS, new ArrayBlockingQueue<Runnable>(numThreads + 1));
this.timeout = unit.toMillis(timeout);
}
#Override
protected void beforeExecute(Thread thread, Runnable runnable) {
Thread interruptionThread = new Thread(new Runnable() {
#Override
public void run() {
try {
// Wait until timeout and interrupt this thread
Thread.sleep(timeout);
System.out.println("The runnable times out.");
thread.interrupt();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
});
interruptionThread.start();
}
}
Usage:
public static void main(String[] args) {
Runnable abcdRunnable = new Runnable() {
#Override
public void run() {
System.out.println("abcdRunnable started");
try {
Thread.sleep(20000);
} catch (InterruptedException e) {
// logger.info("The runnable times out.");
}
System.out.println("abcdRunnable ended");
}
};
Runnable xyzwRunnable = new Runnable() {
#Override
public void run() {
System.out.println("xyzwRunnable started");
try {
Thread.sleep(20000);
} catch (InterruptedException e) {
// logger.info("The runnable times out.");
}
System.out.println("xyzwRunnable ended");
}
};
int numThreads = 2, timeout = 5;
ExecutorService timedExecutor = new TimedExecutorService(numThreads, timeout, TimeUnit.SECONDS);
timedExecutor.execute(abcdRunnable);
timedExecutor.execute(xyzwRunnable);
timedExecutor.shutdown();
}
Now , l meet a issue like this. It happens to decode picture. The process of decode takes too much time that the screen keep black. l add a time controler: when the time is too long, then pop up from the current Thread.
The following is the diff:
ExecutorService executor = Executors.newSingleThreadExecutor();
Future<Bitmap> future = executor.submit(new Callable<Bitmap>() {
#Override
public Bitmap call() throws Exception {
Bitmap bitmap = decodeAndScaleBitmapFromStream(context, inputUri);// do some time consuming operation
return null;
}
});
try {
Bitmap result = future.get(1, TimeUnit.SECONDS);
} catch (TimeoutException e){
future.cancel(true);
}
executor.shutdown();
return (bitmap!= null);
I had the same problem. So i came up with a simple solution like this.
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;
}
}
Guarantees that if block didn't execute within the time limit. the process will terminate and throws an exception.
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
}