Handling exceptions from Java ExecutorService tasks - java

I'm trying to use Java's ThreadPoolExecutor class to run a large number of heavy weight tasks with a fixed number of threads. Each of the tasks has many places during which it may fail due to exceptions.
I've subclassed ThreadPoolExecutor and I've overridden the afterExecute method which is supposed to provide any uncaught exceptions encountered while running a task. However, I can't seem to make it work.
For example:
public class ThreadPoolErrors extends ThreadPoolExecutor {
public ThreadPoolErrors() {
super( 1, // core threads
1, // max threads
1, // timeout
TimeUnit.MINUTES, // timeout units
new LinkedBlockingQueue<Runnable>() // work queue
);
}
protected void afterExecute(Runnable r, Throwable t) {
super.afterExecute(r, t);
if(t != null) {
System.out.println("Got an error: " + t);
} else {
System.out.println("Everything's fine--situation normal!");
}
}
public static void main( String [] args) {
ThreadPoolErrors threadPool = new ThreadPoolErrors();
threadPool.submit(
new Runnable() {
public void run() {
throw new RuntimeException("Ouch! Got an error.");
}
}
);
threadPool.shutdown();
}
}
The output from this program is "Everything's fine--situation normal!" even though the only Runnable submitted to the thread pool throws an exception. Any clue to what's going on here?
Thanks!

WARNING: It should be noted that this solution will block the calling thread in future.get().
If you want to process exceptions thrown by the task, then it is generally better to use Callable rather than Runnable.
Callable.call() is permitted to throw checked exceptions, and these get propagated back to the calling thread:
Callable task = ...
Future future = executor.submit(task);
// do something else in the meantime, and then...
try {
future.get();
} catch (ExecutionException ex) {
ex.getCause().printStackTrace();
}
If Callable.call() throws an exception, this will be wrapped in an ExecutionException and thrown by Future.get().
This is likely to be much preferable to subclassing ThreadPoolExecutor. It also gives you the opportunity to re-submit the task if the exception is a recoverable one.

From the docs:
Note: When actions are enclosed in
tasks (such as FutureTask) either
explicitly or via methods such as
submit, these task objects catch and
maintain computational exceptions, and
so they do not cause abrupt
termination, and the internal
exceptions are not passed to this
method.
When you submit a Runnable, it'll get wrapped in a Future.
Your afterExecute should be something like this:
public final class ExtendedExecutor extends ThreadPoolExecutor {
// ...
protected void afterExecute(Runnable r, Throwable t) {
super.afterExecute(r, t);
if (t == null && r instanceof Future<?>) {
try {
Future<?> future = (Future<?>) r;
if (future.isDone()) {
future.get();
}
} catch (CancellationException ce) {
t = ce;
} catch (ExecutionException ee) {
t = ee.getCause();
} catch (InterruptedException ie) {
Thread.currentThread().interrupt();
}
}
if (t != null) {
System.out.println(t);
}
}
}

The explanation for this behavior is right in the javadoc for afterExecute:
Note: When actions are enclosed in
tasks (such as FutureTask) either
explicitly or via methods such as
submit, these task objects catch and
maintain computational exceptions, and
so they do not cause abrupt
termination, and the internal
exceptions are not passed to this
method.

I got around it by wrapping the supplied runnable submitted to the executor.
CompletableFuture.runAsync(() -> {
try {
runnable.run();
} catch (Throwable e) {
Log.info(Concurrency.class, "runAsync", e);
}
}, executorService);

I'm using VerboseRunnable class from jcabi-log, which swallows all exceptions and logs them. Very convenient, for example:
import com.jcabi.log.VerboseRunnable;
scheduler.scheduleWithFixedDelay(
new VerboseRunnable(
Runnable() {
public void run() {
// the code, which may throw
}
},
true // it means that all exceptions will be swallowed and logged
),
1, 1, TimeUnit.MILLISECONDS
);

Another solution would be to use the ManagedTask and ManagedTaskListener.
You need a Callable or Runnable which implements the interface ManagedTask.
The method getManagedTaskListener returns the instance you want.
public ManagedTaskListener getManagedTaskListener() {
And you implement in ManagedTaskListener the taskDone method:
#Override
public void taskDone(Future<?> future, ManagedExecutorService executor, Object task, Throwable exception) {
if (exception != null) {
LOGGER.log(Level.SEVERE, exception.getMessage());
}
}
More details about managed task lifecycle and listener.

This works
It is derived from SingleThreadExecutor, but you can adapt it easily
Java 8 lamdas code, but easy to fix
It will create a Executor with a single thread, that can get a lot of tasks; and will wait for the current one to end execution to begin with the next
In case of uncaugth error or exception the uncaughtExceptionHandler will catch it
public final class SingleThreadExecutorWithExceptions {
public static ExecutorService newSingleThreadExecutorWithExceptions(final Thread.UncaughtExceptionHandler uncaughtExceptionHandler) {
ThreadFactory factory = (Runnable runnable) -> {
final Thread newThread = new Thread(runnable, "SingleThreadExecutorWithExceptions");
newThread.setUncaughtExceptionHandler( (final Thread caugthThread,final Throwable throwable) -> {
uncaughtExceptionHandler.uncaughtException(caugthThread, throwable);
});
return newThread;
};
return new FinalizableDelegatedExecutorService
(new ThreadPoolExecutor(1, 1,
0L, TimeUnit.MILLISECONDS,
new LinkedBlockingQueue(),
factory){
protected void afterExecute(Runnable runnable, Throwable throwable) {
super.afterExecute(runnable, throwable);
if (throwable == null && runnable instanceof Future) {
try {
Future future = (Future) runnable;
if (future.isDone()) {
future.get();
}
} catch (CancellationException ce) {
throwable = ce;
} catch (ExecutionException ee) {
throwable = ee.getCause();
} catch (InterruptedException ie) {
Thread.currentThread().interrupt(); // ignore/reset
}
}
if (throwable != null) {
uncaughtExceptionHandler.uncaughtException(Thread.currentThread(),throwable);
}
}
});
}
private static class FinalizableDelegatedExecutorService
extends DelegatedExecutorService {
FinalizableDelegatedExecutorService(ExecutorService executor) {
super(executor);
}
protected void finalize() {
super.shutdown();
}
}
/**
* A wrapper class that exposes only the ExecutorService methods
* of an ExecutorService implementation.
*/
private static class DelegatedExecutorService extends AbstractExecutorService {
private final ExecutorService e;
DelegatedExecutorService(ExecutorService executor) { e = executor; }
public void execute(Runnable command) { e.execute(command); }
public void shutdown() { e.shutdown(); }
public List shutdownNow() { return e.shutdownNow(); }
public boolean isShutdown() { return e.isShutdown(); }
public boolean isTerminated() { return e.isTerminated(); }
public boolean awaitTermination(long timeout, TimeUnit unit)
throws InterruptedException {
return e.awaitTermination(timeout, unit);
}
public Future submit(Runnable task) {
return e.submit(task);
}
public Future submit(Callable task) {
return e.submit(task);
}
public Future submit(Runnable task, T result) {
return e.submit(task, result);
}
public List> invokeAll(Collection> tasks)
throws InterruptedException {
return e.invokeAll(tasks);
}
public List> invokeAll(Collection> tasks,
long timeout, TimeUnit unit)
throws InterruptedException {
return e.invokeAll(tasks, timeout, unit);
}
public T invokeAny(Collection> tasks)
throws InterruptedException, ExecutionException {
return e.invokeAny(tasks);
}
public T invokeAny(Collection> tasks,
long timeout, TimeUnit unit)
throws InterruptedException, ExecutionException, TimeoutException {
return e.invokeAny(tasks, timeout, unit);
}
}
private SingleThreadExecutorWithExceptions() {}
}

This is because of AbstractExecutorService :: submit is wrapping your runnable into RunnableFuture (nothing but FutureTask) like below
AbstractExecutorService.java
public Future<?> submit(Runnable task) {
if (task == null) throw new NullPointerException();
RunnableFuture<Void> ftask = newTaskFor(task, null); /////////HERE////////
execute(ftask);
return ftask;
}
Then execute will pass it to Worker and Worker.run() will call the below.
ThreadPoolExecutor.java
final void runWorker(Worker w) {
Thread wt = Thread.currentThread();
Runnable task = w.firstTask;
w.firstTask = null;
w.unlock(); // allow interrupts
boolean completedAbruptly = true;
try {
while (task != null || (task = getTask()) != null) {
w.lock();
// If pool is stopping, ensure thread is interrupted;
// if not, ensure thread is not interrupted. This
// requires a recheck in second case to deal with
// shutdownNow race while clearing interrupt
if ((runStateAtLeast(ctl.get(), STOP) ||
(Thread.interrupted() &&
runStateAtLeast(ctl.get(), STOP))) &&
!wt.isInterrupted())
wt.interrupt();
try {
beforeExecute(wt, task);
Throwable thrown = null;
try {
task.run(); /////////HERE////////
} catch (RuntimeException x) {
thrown = x; throw x;
} catch (Error x) {
thrown = x; throw x;
} catch (Throwable x) {
thrown = x; throw new Error(x);
} finally {
afterExecute(task, thrown);
}
} finally {
task = null;
w.completedTasks++;
w.unlock();
}
}
completedAbruptly = false;
} finally {
processWorkerExit(w, completedAbruptly);
}
}
Finally task.run(); in the above code call will call
FutureTask.run(). Here is the exception handler code, because of
this you are NOT getting the expected exception.
class FutureTask<V> implements RunnableFuture<V>
public void run() {
if (state != NEW ||
!UNSAFE.compareAndSwapObject(this, runnerOffset,
null, Thread.currentThread()))
return;
try {
Callable<V> c = callable;
if (c != null && state == NEW) {
V result;
boolean ran;
try {
result = c.call();
ran = true;
} catch (Throwable ex) { /////////HERE////////
result = null;
ran = false;
setException(ex);
}
if (ran)
set(result);
}
} finally {
// runner must be non-null until state is settled to
// prevent concurrent calls to run()
runner = null;
// state must be re-read after nulling runner to prevent
// leaked interrupts
int s = state;
if (s >= INTERRUPTING)
handlePossibleCancellationInterrupt(s);
}
}

If you want to monitor the execution of task, you could spin 1 or 2 threads (maybe more depending on the load) and use them to take tasks from an ExecutionCompletionService wrapper.

The doc's example wasn't giving me the results I wanted.
When a Thread process was abandoned (with explicit interput();s) Exceptions were appearing.
Also I wanted to keep the "System.exit" functionality that a normal main thread has with a typical throw, I wanted this so that the programmer was not forced to work on the code having to worry on it's context (... a thread), If any error appears, it must either be a programming error, or the case must be solved in place with a manual catch... no need for overcomplexities really.
So I changed the code to match my needs.
#Override
protected void afterExecute(Runnable r, Throwable t) {
super.afterExecute(r, t);
if (t == null && r instanceof Future<?>) {
Future<?> future = (Future<?>) r;
boolean terminate = false;
try {
future.get();
} catch (ExecutionException e) {
terminate = true;
e.printStackTrace();
} catch (InterruptedException | CancellationException ie) {// ignore/reset
Thread.currentThread().interrupt();
} finally {
if (terminate) System.exit(0);
}
}
}
Be cautious though, this code basically transforms your threads into a main thread Exception-wise, while keeping all it's parallel properties... But let's be real, designing architectures in function of the system's parallel mechanism (extends Thread) is the wrong approach IMHO... unless an event driven design is strictly required....but then... if that is the requirement the question is: Is the ExecutorService even needed in this case?... maybe not.

If your ExecutorService comes from an external source (i. e. it's not possible to subclass ThreadPoolExecutor and override afterExecute()), you can use a dynamic proxy to achieve the desired behavior:
public static ExecutorService errorAware(final ExecutorService executor) {
return (ExecutorService) Proxy.newProxyInstance(Thread.currentThread().getContextClassLoader(),
new Class[] {ExecutorService.class},
(proxy, method, args) -> {
if (method.getName().equals("submit")) {
final Object arg0 = args[0];
if (arg0 instanceof Runnable) {
args[0] = new Runnable() {
#Override
public void run() {
final Runnable task = (Runnable) arg0;
try {
task.run();
if (task instanceof Future<?>) {
final Future<?> future = (Future<?>) task;
if (future.isDone()) {
try {
future.get();
} catch (final CancellationException ce) {
// Your error-handling code here
ce.printStackTrace();
} catch (final ExecutionException ee) {
// Your error-handling code here
ee.getCause().printStackTrace();
} catch (final InterruptedException ie) {
Thread.currentThread().interrupt();
}
}
}
} catch (final RuntimeException re) {
// Your error-handling code here
re.printStackTrace();
throw re;
} catch (final Error e) {
// Your error-handling code here
e.printStackTrace();
throw e;
}
}
};
} else if (arg0 instanceof Callable<?>) {
args[0] = new Callable<Object>() {
#Override
public Object call() throws Exception {
final Callable<?> task = (Callable<?>) arg0;
try {
return task.call();
} catch (final Exception e) {
// Your error-handling code here
e.printStackTrace();
throw e;
} catch (final Error e) {
// Your error-handling code here
e.printStackTrace();
throw e;
}
}
};
}
}
return method.invoke(executor, args);
});
}

This is similar to mmm's solution, but a bit more understandable. Have your tasks extend an abstract class that wraps the run() method.
public abstract Task implements Runnable {
public abstract void execute();
public void run() {
try {
execute();
} catch (Throwable t) {
// handle it
}
}
}
public MySampleTask extends Task {
public void execute() {
// heavy, error-prone code here
}
}

Instead of subclassing ThreadPoolExecutor, I would provide it with a ThreadFactory instance that creates new Threads and provides them with an UncaughtExceptionHandler

Related

Calling a method with multiple argument

I've been using the Java 8 Streams for a while. I came across a situation where I need to stream through a List and pass each element to a method of a class that is not static.
List<String> emps = new ArrayList<>();
emps.add("ABC");
emps.add("DEF");
emps.add("GHI");
I want to call the "start" method of EmpDataGenerator.
EmpDataGenerator generator = new EmpDataGenerator(
Executors.newFixedThreadPool(emps.size()));
I have tried this, but it's not working
emps.stream().map(e-> generator.start(e));
public class EmpDataGenerator {
// Used to signal a graceful shutdown
private volatile boolean stop = false;
private final ExecutorService executor;
public EmpDataGenerator(ExecutorService executor) {
this.executor = executor;
}
public void start(String name ) {
Runnable generator = () -> {
try {
while (!stop) {
//do some processing
}
System.out.println("Broke while loop, stop " + stop);
} catch (Exception e) {
System.out.println("EmpDataGenerator thread caught an exception and halted!");
throw e;
}
};
executor.execute(generator);
}
public void stop() {
stop = true;
// The shutdown the executor (after waiting a bit to be nice)
try {
executor.awaitTermination(1000, TimeUnit.MILLISECONDS);
} catch (InterruptedException e) {
// Purposely ignore any InterruptedException
Thread.currentThread().interrupt();
}
executor.shutdownNow();
}
}
A map must take an input and transform it to something. The start method is void.
There is no need for streams here. A simple forEach should do.
emps.forEach(e-> generator.start(e));
or
emps.forEach(generator::start);

Catch Java exception from Runnable in Unit test

I have the below code
public final class JoinableTaskPool<T> extends ABC {
private int taskCounter;
private final Object monitor;
private final ExtendedThreadPoolExecutor service;
private final CompletionService<T> compService;
public Future<T> submit(final Callable<T> task) {
final Future<T> result = compService.submit(task);
service.submit(new Runnable() {
public void run() {
try {
final Future<T> result = compService.take();
try {
handler.processResult(result);
} catch (final Throwable t) {
throw new SearchException("Task has an error", t);
}
} catch (InterruptedException e) {
throw new SearchException("Task has an error", e);
}
}
}
return result;
}
public void join() {
synchronized (monitor) {
while (taskCounter != 0) {
try {
monitor.wait();
} catch (InterruptedException e) {
error(e, "Interrupted in join");
}
}
}
}
The ExtendedThreadPoolExecutor class is defined as follows
public class ExtendedThreadPoolExecutor extends ThreadPoolExecutor {
public ExtendedThreadPoolExecutor(int corePoolSize, int maximumPoolSize, long keepAliveTime, TimeUnit unit, BlockingQueue<Runnable> workQueue, ThreadFactory threadFactory) {
super(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue, threadFactory);
}
#Override
protected void afterExecute(Runnable r, Throwable t) {
super.afterExecute(r, t);
if(t != null) {
throw new SearchException("Error while executing the task", t);
}
}
}
I am trying to write a unit test for this method. Below is the method
#RunWith(MockitoJUnitRunner.class)
public class TestJoinableTaskPool<T> {
private JoinableTaskPool<T> pool;
#Before
public void setUp() {
pool = new JoinableTaskPool<T>(1);
}
#After
public void tearDown() {
pool.shutdown();
}
#Test (expected = SearchException.class)
public void testSubmit() throws Exception{
Callable task = (Callable<T>) () -> null;
Mockito.when(pool.getFinishHandler().processResult(result))
.thenThrow(RuntimeException.class);
pool.submit(task);
}
}
Since the SearchException exception is thrown in runnable, there is no way to access it outside the submit method. If I would have returned the Future returned by executorService.submit, I could have done a future.get() to get an exception, but I am returning another future (result variable).
So while writing the unit test I am not able to get the exception thrown.
Also I have overriden the afterExecute() in an effort to catch exception from unit test,but couldnt find a way to call it.
How do I test this exception thrown from the runnable from a unit test.
Any help would be appreciated.
Putting aside that his code smells a mile away, what you can do is to create additional interface eg
public interface MyErrorHandler {
handleError(Exception e)
implement it in your executor pools and call it on exception. Then you can use use Mockito.spy to see if tha method have been called or not on MyErrorHandler (cglib should allow you to do that even withount additional intrerface.)
alternatively you can define that MyExceptionHandler instance should be passed to an executor (via constructor or setter) so you will be able to provide use case dependent implementation of such callback

How to interrupt underlying execution of CompletableFuture

I know that CompletableFuture design does not control its execution with interruptions, but I suppose some of you might have this problem. CompletableFutures are very good way to compose async execution, but given the case when you want the underlying execution to be interrupted or stopped when future is canceled, how do we do that? Or we must just accept that any canceled or manually completed CompletableFuture will not impact the thread working out there to complete it?
That is, in my opinion, obviously a useless work that takes time of executor worker. I wonder what approach or design might help in this case?
UPDATE
Here is a simple test for this
public class SimpleTest {
#Test
public void testCompletableFuture() throws Exception {
CompletableFuture<Void> cf = CompletableFuture.runAsync(()->longOperation());
bearSleep(1);
//cf.cancel(true);
cf.complete(null);
System.out.println("it should die now already");
bearSleep(7);
}
public static void longOperation(){
System.out.println("started");
bearSleep(5);
System.out.println("completed");
}
private static void bearSleep(long seconds){
try {
TimeUnit.SECONDS.sleep(seconds);
} catch (InterruptedException e) {
System.out.println("OMG!!! Interrupt!!!");
}
}
}
A CompletableFuture is not related to the asynchronous action that may eventually complete it.
Since (unlike FutureTask) this class has no direct control over the
computation that causes it to be completed, cancellation is treated as
just another form of exceptional completion. Method cancel has the
same effect as completeExceptionally(new CancellationException()).
There may not even be a separate thread working on completing it (there may even be many threads working on it). Even if there is, there's no link from a CompletableFuture to any thread that has a reference to it.
As such, there's nothing you can do through CompletableFuture to interrupt any thread that may be running some task that will complete it. You'll have to write your own logic which tracks any Thread instances which acquire a reference to the CompletableFuture with the intention to complete it.
Here's an example of the type of execution I think you could get away with.
public static void main(String[] args) throws Exception {
ExecutorService service = Executors.newFixedThreadPool(1);
CompletableFuture<String> completable = new CompletableFuture<>();
Future<?> future = service.submit(new Runnable() {
#Override
public void run() {
for (int i = 0; i < 10; i++) {
if (Thread.interrupted()) {
return; // remains uncompleted
}
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
return; // remains uncompleted
}
}
completable.complete("done");
}
});
Thread.sleep(2000);
// not atomic across the two
boolean cancelled = future.cancel(true);
if (cancelled)
completable.cancel(true); // may not have been cancelled if execution has already completed
if (completable.isCancelled()) {
System.out.println("cancelled");
} else if (completable.isCompletedExceptionally()) {
System.out.println("exception");
} else {
System.out.println("success");
}
service.shutdown();
}
This assumes that the task being executed is setup to handle interruptions correctly.
What about this?
public static <T> CompletableFuture<T> supplyAsync(final Supplier<T> supplier) {
final ExecutorService executorService = Executors.newFixedThreadPool(1);
final CompletableFuture<T> cf = new CompletableFuture<T>() {
#Override
public boolean complete(T value) {
if (isDone()) {
return false;
}
executorService.shutdownNow();
return super.complete(value);
}
#Override
public boolean completeExceptionally(Throwable ex) {
if (isDone()) {
return false;
}
executorService.shutdownNow();
return super.completeExceptionally(ex);
}
};
// submit task
executorService.submit(() -> {
try {
cf.complete(supplier.get());
} catch (Throwable ex) {
cf.completeExceptionally(ex);
}
});
return cf;
}
Simple Test:
CompletableFuture<String> cf = supplyAsync(() -> {
try {
Thread.sleep(1000L);
} catch (Exception e) {
System.out.println("got interrupted");
return "got interrupted";
}
System.out.println("normal complete");
return "normal complete";
});
cf.complete("manual complete");
System.out.println(cf.get());
I don't like the idea of having to create an Executor service every time, but maybe you can find a way to reuse the ForkJoinPool.
If you use
cf.get();
instead of
cf.join();
The thread waiting on the completion can be interrupted. This bit me in the a**, so I'm just putting it out there. You'd then need to propagate this interruption further / use cf.cancel(...) to really finish the execution.
I had similar issue wherein I needed to simulate a InterruptedException.
I mocked the method call that is supposed to return the CompletetableFuture, and I put a spy on return value such that CompletableFuture#get will throw the exception.
It worked as I expected, and I was able to test that code handled the exception correctly.
CompletableFuture spiedFuture = spy(CompletableFuture.completedFuture(null));
when(spiedFuture .get()).thenThrow(new InterruptedException());
when(servuce.getById(anyString())).thenReturn(spiedFuture );
Here is a ultra-short version to create a Future task that can be cancelled:
public static <T> Future<T> supplyAsync(Function<Future<T>, T> operation) {
CompletableFuture<T> future = new CompletableFuture<>();
return future.completeAsync(() -> operation.apply(future));
}
The CompletableFuture is passed to the operation Function to be able to check the cancel status of the Future:
Future<Result> future = supplyAsync(task -> {
while (!task.isCancelled()) {
// computation
}
return result;
});
// later you may cancel
future.cancel(false);
// or retrieve the result
Result result = future.get(5, TimeUnit.SECONDS);
This however does not interrupt the Thread running the operation. If you also want to be able to interrupt the Thread, then you have to store a reference to it and override Future.cancel(..) to interrupt it.
public static <T> Future<T> supplyAsync(Function<Future<T>, T> action) {
return supplyAsync(action, r -> new Thread(r).start());
}
public static <T> Future<T> supplyAsync(Function<Future<T>, T> action, Executor executor) {
AtomicReference<Thread> interruptThread = new AtomicReference<>();
CompletableFuture<T> future = new CompletableFuture<>() {
#Override
public boolean cancel(boolean mayInterruptIfRunning) {
if (!interruptThread.compareAndSet(null, Thread.currentThread())
&& mayInterruptIfRunning) {
interruptThread.get().interrupt();
}
return super.cancel(mayInterruptIfRunning);
}
};
executor.execute(() -> {
if (interruptThread.compareAndSet(null, Thread.currentThread())) try {
future.complete(action.apply(future));
} catch (Throwable e) {
future.completeExceptionally(e);
}
});
return future;
}
The following test checks that the Thread executing our Function got interrupted:
#Test
void supplyAsyncWithCancelOnInterrupt() throws Exception {
Object lock = new Object();
CountDownLatch done = new CountDownLatch(1);
CountDownLatch started = new CountDownLatch(1);
Future<Object> future = supplyAsync(m -> {
started.countDown();
synchronized (lock) {
try {
lock.wait(); // let's get interrupted
} catch (InterruptedException e) {
done.countDown();
}
}
return null;
});
assertFalse(future.isCancelled());
assertFalse(future.isDone());
assertTrue(started.await(5, TimeUnit.SECONDS));
assertTrue(future.cancel(true));
assertTrue(future.isCancelled());
assertTrue(future.isDone());
assertThrows(CancellationException.class, () -> future.get());
assertTrue(done.await(5, TimeUnit.SECONDS));
}
What about?
/** #return {#link CompletableFuture} which when cancelled will interrupt the supplier
*/
public static <T> CompletableFuture<T> supplyAsyncInterruptibly(Supplier<T> supplier, Executor executor) {
return produceInterruptibleCompletableFuture((s) -> CompletableFuture.supplyAsync(s, executor), supplier);
}
// in case we want to do the same for similar methods later
private static <T> CompletableFuture<T> produceInterruptibleCompletableFuture(
Function<Supplier<T>,CompletableFuture<T>> completableFutureAsyncSupplier, Supplier<T> action) {
FutureTask<T> task = new FutureTask<>(action::get);
return addCancellationAction(completableFutureAsyncSupplier.apply(asSupplier(task)), () ->
task.cancel(true));
}
/** Ensures the specified action is executed if the given {#link CompletableFuture} is cancelled.
*/
public static <T> CompletableFuture<T> addCancellationAction(CompletableFuture<T> completableFuture,
#NonNull Runnable onCancellationAction) {
completableFuture.whenComplete((result, throwable) -> {
if (completableFuture.isCancelled()) {
onCancellationAction.run();
}
});
return completableFuture; // return original CompletableFuture
}
/** #return {#link Supplier} wrapper for the given {#link RunnableFuture} which calls {#link RunnableFuture#run()}
* followed by {#link RunnableFuture#get()}.
*/
public static <T> Supplier<T> asSupplier(RunnableFuture<T> futureTask) throws CompletionException {
return () -> {
try {
futureTask.run();
try {
return futureTask.get();
} catch (ExecutionException e) { // unwrap ExecutionExceptions
final Throwable cause = e.getCause();
throw (cause != null) ? cause : e;
}
} catch (CompletionException e) {
throw e;
} catch (Throwable t) {
throw new CompletionException(t);
}
};
}

Waiting on a list of Future

I have a method which returns a List of futures
List<Future<O>> futures = getFutures();
Now I want to wait until either all futures are done processing successfully or any of the tasks whose output is returned by a future throws an exception. Even if one task throws an exception, there is no point in waiting for the other futures.
Simple approach would be to
wait() {
For(Future f : futures) {
try {
f.get();
} catch(Exception e) {
//TODO catch specific exception
// this future threw exception , means somone could not do its task
return;
}
}
}
But the problem here is if, for example, the 4th future throws an exception, then I will wait unnecessarily for the first 3 futures to be available.
How to solve this? Will count down latch help in any way? I'm unable to use Future isDone because the java doc says
boolean isDone()
Returns true if this task completed. Completion may be due to normal termination, an exception, or cancellation -- in all of these cases, this method will return true.
You can use a CompletionService to receive the futures as soon as they are ready and if one of them throws an exception cancel the processing. Something like this:
Executor executor = Executors.newFixedThreadPool(4);
CompletionService<SomeResult> completionService =
new ExecutorCompletionService<SomeResult>(executor);
//4 tasks
for(int i = 0; i < 4; i++) {
completionService.submit(new Callable<SomeResult>() {
public SomeResult call() {
...
return result;
}
});
}
int received = 0;
boolean errors = false;
while(received < 4 && !errors) {
Future<SomeResult> resultFuture = completionService.take(); //blocks if none available
try {
SomeResult result = resultFuture.get();
received ++;
... // do something with the result
}
catch(Exception e) {
//log
errors = true;
}
}
I think you can further improve to cancel any still executing tasks if one of them throws an error.
If you are using Java 8 then you can do this easier with CompletableFuture and CompletableFuture.allOf, which applies the callback only after all supplied CompletableFutures are done.
// Waits for *all* futures to complete and returns a list of results.
// If *any* future completes exceptionally then the resulting future will also complete exceptionally.
public static <T> CompletableFuture<List<T>> all(List<CompletableFuture<T>> futures) {
CompletableFuture[] cfs = futures.toArray(new CompletableFuture[futures.size()]);
return CompletableFuture.allOf(cfs)
.thenApply(ignored -> futures.stream()
.map(CompletableFuture::join)
.collect(Collectors.toList())
);
}
Use a CompletableFuture in Java 8
// Kick of multiple, asynchronous lookups
CompletableFuture<User> page1 = gitHubLookupService.findUser("Test1");
CompletableFuture<User> page2 = gitHubLookupService.findUser("Test2");
CompletableFuture<User> page3 = gitHubLookupService.findUser("Test3");
// Wait until they are all done
CompletableFuture.allOf(page1,page2,page3).join();
logger.info("--> " + page1.get());
You can use an ExecutorCompletionService. The documentation even has an example for your exact use-case:
Suppose instead that you would like to use the first non-null result of the set of tasks, ignoring any that encounter exceptions, and cancelling all other tasks when the first one is ready:
void solve(Executor e, Collection<Callable<Result>> solvers) throws InterruptedException {
CompletionService<Result> ecs = new ExecutorCompletionService<Result>(e);
int n = solvers.size();
List<Future<Result>> futures = new ArrayList<Future<Result>>(n);
Result result = null;
try {
for (Callable<Result> s : solvers)
futures.add(ecs.submit(s));
for (int i = 0; i < n; ++i) {
try {
Result r = ecs.take().get();
if (r != null) {
result = r;
break;
}
} catch (ExecutionException ignore) {
}
}
} finally {
for (Future<Result> f : futures)
f.cancel(true);
}
if (result != null)
use(result);
}
The important thing to notice here is that ecs.take() will get the first completed task, not just the first submitted one. Thus you should get them in the order of finishing the execution (or throwing an exception).
If you are using Java 8 and don't want to manipulate CompletableFutures, I have written a tool to retrieve results for a List<Future<T>> using streaming. The key is that you are forbidden to map(Future::get) as it throws.
public final class Futures
{
private Futures()
{}
public static <E> Collector<Future<E>, Collection<E>, List<E>> present()
{
return new FutureCollector<>();
}
private static class FutureCollector<T> implements Collector<Future<T>, Collection<T>, List<T>>
{
private final List<Throwable> exceptions = new LinkedList<>();
#Override
public Supplier<Collection<T>> supplier()
{
return LinkedList::new;
}
#Override
public BiConsumer<Collection<T>, Future<T>> accumulator()
{
return (r, f) -> {
try
{
r.add(f.get());
}
catch (InterruptedException e)
{}
catch (ExecutionException e)
{
exceptions.add(e.getCause());
}
};
}
#Override
public BinaryOperator<Collection<T>> combiner()
{
return (l1, l2) -> {
l1.addAll(l2);
return l1;
};
}
#Override
public Function<Collection<T>, List<T>> finisher()
{
return l -> {
List<T> ret = new ArrayList<>(l);
if (!exceptions.isEmpty())
throw new AggregateException(exceptions, ret);
return ret;
};
}
#Override
public Set<java.util.stream.Collector.Characteristics> characteristics()
{
return java.util.Collections.emptySet();
}
}
This needs an AggregateException that works like C#'s
public class AggregateException extends RuntimeException
{
/**
*
*/
private static final long serialVersionUID = -4477649337710077094L;
private final List<Throwable> causes;
private List<?> successfulElements;
public AggregateException(List<Throwable> causes, List<?> l)
{
this.causes = causes;
successfulElements = l;
}
public AggregateException(List<Throwable> causes)
{
this.causes = causes;
}
#Override
public synchronized Throwable getCause()
{
return this;
}
public List<Throwable> getCauses()
{
return causes;
}
public List<?> getSuccessfulElements()
{
return successfulElements;
}
public void setSuccessfulElements(List<?> successfulElements)
{
this.successfulElements = successfulElements;
}
}
This component acts exactly as C#'s Task.WaitAll. I am working on a variant that does the same as CompletableFuture.allOf (equivalento to Task.WhenAll)
The reason why I did this is that I am using Spring's ListenableFuture and don't want to port to CompletableFuture despite it is a more standard way
In case that you want combine a List of CompletableFutures, you can do this :
List<CompletableFuture<Void>> futures = new ArrayList<>();
// ... Add futures to this ArrayList of CompletableFutures
// CompletableFuture.allOf() method demand a variadic arguments
// You can use this syntax to pass a List instead
CompletableFuture<Void> allFutures = CompletableFuture.allOf(
futures.toArray(new CompletableFuture[futures.size()]));
// Wait for all individual CompletableFuture to complete
// All individual CompletableFutures are executed in parallel
allFutures.get();
For more details on Future & CompletableFuture, useful links:
1. Future: https://www.baeldung.com/java-future
2. CompletableFuture: https://www.baeldung.com/java-completablefuture
3. CompletableFuture: https://www.callicoder.com/java-8-completablefuture-tutorial/
I've got a utility class that contains these:
#FunctionalInterface
public interface CheckedSupplier<X> {
X get() throws Throwable;
}
public static <X> Supplier<X> uncheckedSupplier(final CheckedSupplier<X> supplier) {
return () -> {
try {
return supplier.get();
} catch (final Throwable checkedException) {
throw new IllegalStateException(checkedException);
}
};
}
Once you have that, using a static import, you can simple wait for all futures like this:
futures.stream().forEach(future -> uncheckedSupplier(future::get).get());
you can also collect all their results like this:
List<MyResultType> results = futures.stream()
.map(future -> uncheckedSupplier(future::get).get())
.collect(Collectors.toList());
Just revisiting my old post and noticing that you had another grief:
But the problem here is if, for example, the 4th future throws an exception, then I will wait unnecessarily for the first 3 futures to be available.
In this case, the simple solution is to do this in parallel:
futures.stream().parallel()
.forEach(future -> uncheckedSupplier(future::get).get());
This way the first exception, although it will not stop the future, will break the forEach-statement, like in the serial example, but since all wait in parallel, you won't have to wait for the first 3 to complete.
maybe this would help (nothing would replaced with raw thread, yeah!)
I suggest run each Future guy with a separated thread (they goes parallel), then when ever one of the got error, it just signal the manager(Handler class).
class Handler{
//...
private Thread thisThread;
private boolean failed=false;
private Thread[] trds;
public void waitFor(){
thisThread=Thread.currentThread();
List<Future<Object>> futures = getFutures();
trds=new Thread[futures.size()];
for (int i = 0; i < trds.length; i++) {
RunTask rt=new RunTask(futures.get(i), this);
trds[i]=new Thread(rt);
}
synchronized (this) {
for(Thread tx:trds){
tx.start();
}
}
for(Thread tx:trds){
try {tx.join();
} catch (InterruptedException e) {
System.out.println("Job failed!");break;
}
}if(!failed){System.out.println("Job Done");}
}
private List<Future<Object>> getFutures() {
return null;
}
public synchronized void cancelOther(){if(failed){return;}
failed=true;
for(Thread tx:trds){
tx.stop();//Deprecated but works here like a boss
}thisThread.interrupt();
}
//...
}
class RunTask implements Runnable{
private Future f;private Handler h;
public RunTask(Future f,Handler h){this.f=f;this.h=h;}
public void run(){
try{
f.get();//beware about state of working, the stop() method throws ThreadDeath Error at any thread state (unless it blocked by some operation)
}catch(Exception e){System.out.println("Error, stopping other guys...");h.cancelOther();}
catch(Throwable t){System.out.println("Oops, some other guy has stopped working...");}
}
}
I have to say the above code would error(didn't check), but I hope I could explain the solution. please have a try.
/**
* execute suppliers as future tasks then wait / join for getting results
* #param functors a supplier(s) to execute
* #return a list of results
*/
private List getResultsInFuture(Supplier<?>... functors) {
CompletableFuture[] futures = stream(functors)
.map(CompletableFuture::supplyAsync)
.collect(Collectors.toList())
.toArray(new CompletableFuture[functors.length]);
CompletableFuture.allOf(futures).join();
return stream(futures).map(a-> {
try {
return a.get();
} catch (InterruptedException | ExecutionException e) {
//logger.error("an error occurred during runtime execution a function",e);
return null;
}
}).collect(Collectors.toList());
};
The CompletionService will take your Callables with the .submit() method and you can retrieve the computed futures with the .take() method.
One thing you must not forget is to terminate the ExecutorService by calling the .shutdown() method. Also you can only call this method when you have saved a reference to the executor service so make sure to keep one.
Example code - For a fixed number of work items to be worked on in parallel:
ExecutorService service = Executors.newFixedThreadPool(Runtime.getRuntime().availableProcessors());
CompletionService<YourCallableImplementor> completionService =
new ExecutorCompletionService<YourCallableImplementor>(service);
ArrayList<Future<YourCallableImplementor>> futures = new ArrayList<Future<YourCallableImplementor>>();
for (String computeMe : elementsToCompute) {
futures.add(completionService.submit(new YourCallableImplementor(computeMe)));
}
//now retrieve the futures after computation (auto wait for it)
int received = 0;
while(received < elementsToCompute.size()) {
Future<YourCallableImplementor> resultFuture = completionService.take();
YourCallableImplementor result = resultFuture.get();
received ++;
}
//important: shutdown your ExecutorService
service.shutdown();
Example code - For a dynamic number of work items to be worked on in parallel:
public void runIt(){
ExecutorService service = Executors.newFixedThreadPool(Runtime.getRuntime().availableProcessors());
CompletionService<CallableImplementor> completionService = new ExecutorCompletionService<CallableImplementor>(service);
ArrayList<Future<CallableImplementor>> futures = new ArrayList<Future<CallableImplementor>>();
//Initial workload is 8 threads
for (int i = 0; i < 9; i++) {
futures.add(completionService.submit(write.new CallableImplementor()));
}
boolean finished = false;
while (!finished) {
try {
Future<CallableImplementor> resultFuture;
resultFuture = completionService.take();
CallableImplementor result = resultFuture.get();
finished = doSomethingWith(result.getResult());
result.setResult(null);
result = null;
resultFuture = null;
//After work package has been finished create new work package and add it to futures
futures.add(completionService.submit(write.new CallableImplementor()));
} catch (InterruptedException | ExecutionException e) {
//handle interrupted and assert correct thread / work packet count
}
}
//important: shutdown your ExecutorService
service.shutdown();
}
public class CallableImplementor implements Callable{
boolean result;
#Override
public CallableImplementor call() throws Exception {
//business logic goes here
return this;
}
public boolean getResult() {
return result;
}
public void setResult(boolean result) {
this.result = result;
}
}
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
import java.util.stream.Collectors;
import java.util.stream.Stream;
public class Stack2 {
public static void waitFor(List<Future<?>> futures) {
List<Future<?>> futureCopies = new ArrayList<Future<?>>(futures);//contains features for which status has not been completed
while (!futureCopies.isEmpty()) {//worst case :all task worked without exception, then this method should wait for all tasks
Iterator<Future<?>> futureCopiesIterator = futureCopies.iterator();
while (futureCopiesIterator.hasNext()) {
Future<?> future = futureCopiesIterator.next();
if (future.isDone()) {//already done
futureCopiesIterator.remove();
try {
future.get();// no longer waiting
} catch (InterruptedException e) {
//ignore
//only happen when current Thread interrupted
} catch (ExecutionException e) {
Throwable throwable = e.getCause();// real cause of exception
futureCopies.forEach(f -> f.cancel(true));//cancel other tasks that not completed
return;
}
}
}
}
}
public static void main(String[] args) {
ExecutorService executorService = Executors.newFixedThreadPool(3);
Runnable runnable1 = new Runnable (){
public void run(){
try {
Thread.sleep(5000);
} catch (InterruptedException e) {
}
}
};
Runnable runnable2 = new Runnable (){
public void run(){
try {
Thread.sleep(4000);
} catch (InterruptedException e) {
}
}
};
Runnable fail = new Runnable (){
public void run(){
try {
Thread.sleep(1000);
throw new RuntimeException("bla bla bla");
} catch (InterruptedException e) {
}
}
};
List<Future<?>> futures = Stream.of(runnable1,fail,runnable2)
.map(executorService::submit)
.collect(Collectors.toList());
double start = System.nanoTime();
waitFor(futures);
double end = (System.nanoTime()-start)/1e9;
System.out.println(end +" seconds");
}
}
This is what i use to wait for a certain time on a list of futures. I think its cleaner.
CountDownLatch countDownLatch = new CountDownLatch(partitions.size());
// Some parallel work
for (Something tp : somethings) {
completionService.submit(() -> {
try {
work(something)
} catch (ConnectException e) {
} finally {
countDownLatch.countDown();
}
});
}
try {
if (!countDownLatch.await(secondsToWait, TimeUnit.SECONDS)){
}
} catch (InterruptedException e) {
}
A Guava-based solution can be implemented using Futures.FutureCombiner.
Here is the code example given in the javadoc:
final ListenableFuture<Instant> loginDateFuture =
loginService.findLastLoginDate(username);
final ListenableFuture<List<String>> recentCommandsFuture =
recentCommandsService.findRecentCommands(username);
ListenableFuture<UsageHistory> usageFuture =
Futures.whenAllSucceed(loginDateFuture, recentCommandsFuture)
.call(
() ->
new UsageHistory(
username,
Futures.getDone(loginDateFuture),
Futures.getDone(recentCommandsFuture)),
executor);
For more info, see the ListenableFutureExplained section of the user's guide.
If you're curious about how it works under the hood, I suggest looking at this part of the source code: AggregateFuture.java#L127-L186

Can nested threads throw exceptions for parent thread?

I have a Controller class and a Monitor worker thread.
The controller thread looks something like this
public class ControllerA {
public void ControllerA(){
try{
doWork();
}
catch(OhNoException e){
//catch exception
}
public void doWork() throws OhNoException{
new Thread(new Runnable(){
public void run(){
//Needs to monitor resources of ControllerA,
//if things go wrong, it needs to throw OhNoException for its parent
}
}).start();
//do work here
}
}
Is such setup feasible? How do I throw exception to the outside of the thread?
How do I throw exception to the outside of the thread?
Couple ways you can do this. You can set a UncaughtExceptionHandler on the thread or you can use an ExecutorService.submit(Callable) and use the exception that you get from the Future.get().
The easiest way is to use the ExecutorService:
ExecutorService threadPool = Executors.newSingleThreadScheduledExecutor();
Future<Void> future = threadPool.submit(new Callable<Void>() {
public Void call() throws Exception {
// can throw OhNoException here
return null;
}
});
// you need to shut down the pool after submitting the last task
threadPool.shutdown();
try {
// this waits for your background task to finish, it throws if the task threw
future.get();
} catch (ExecutionException e) {
// this is the exception thrown by the call() which could be a OhNoException
Throwable cause = e.getCause();
if (cause instanceof OhNoException) {
throw (OhNoException)cause;
} else if (cause instanceof RuntimeException) {
throw (RuntimeException)cause;
}
}
If you want to use the UncaughtExceptionHandler then you can do something like:
Thread thread = new Thread(...);
final AtomicReference throwableReference = new AtomicReference<Throwable>();
thread.setUncaughtExceptionHandler(new UncaughtExceptionHandler() {
public void uncaughtException(Thread t, Throwable e) {
throwableReference.set(e);
}
});
thread.start();
thread.join();
Throwable throwable = throwableReference.get();
if (throwable != null) {
if (throwable instanceof OhNoException) {
throw (OhNoException)throwable;
} else if (throwable instanceof RuntimeException) {
throw (RuntimeException)throwable;
}
}
Runnable interface cannot throw checked exceptions or return values. In The Callable interface you can call any worker method that return values or throws exceptions. The main tasks of the monitor would be
To declare and initialize the future with the callable instance.
A getResult() method that can have a return future.get(); statement and should declare any checked exceptions in its throws clause for it to be handled by the calling code. In this way we dont have to return a null.

Categories