Concurrent polling downstream dependencies and wait until all of them succeed - java

I am trying to write a simple function that long-polls multiple messages tothe downstream dependency without exhausting it and only exist when all messages succeeded.
I came up with a way to wrap each message polling into a callable and use a ExecutorService to submit a list of callables.
public void poll(final List<Long> messageIdList) {
ExecutorService executorService = Executors.newFixedThreadPool(messageIdList.size());
List<MessageStatusCallable> callables = messageIdList.stream()
.map(messageId -> new MessageStatusCallable(messageId)).collect(Collectors.toList());
boolean allSuccess = false;
try {
allSuccess = executorService.invokeAll(callables).stream().allMatch(success -> {
try {
return success.get().equals(Boolean.TRUE);
} catch (InterruptedException e) {
e.printStackTrace();
return false;
} catch (ExecutionException e) {
e.printStackTrace();
return false;
}
});
} catch (InterruptedException e) {
e.printStackTrace();
}
}
private class MessageStatusCallable implements Callable<Boolean> {
private Long messageId;
public MessageStatusCallable(Long messageId) {
this.messageId = messageId;
}
/**
* Computes a result, or throws an exception if unable to do so.
*
* #return computed result
* #throws Exception if unable to compute a result
*/
#Override
public Boolean call() throws Exception {
String messageStatus = downstreamService.getMessageStatus(messageId);
while(messageStatus == null || !messageStatus.equals( STATUS_VALUE_SUCCEEDED) {
messageStatus = messageLogToControlServer.getMessageStatus(messageId);
Thread.sleep(TimeUnit.MICROSECONDS.toMillis(100));
}
LOG.info("Message: " + messageId + " Succeded");
return true;
}
}
I wonder if there is a better way to achieve this since Thread.sleep is blocking and ugly.

I'm not sure this is the best solution but it occurred to me you could use a CountDownLatch and ScheduledExecutorService.
public void poll(final List<Long> messageIdList) throws InterruptedException {
CountDownLatch latch = new CountDownLatch(messageIdList.size());
ScheduledExecutorService executorService = Executors.newScheduledThreadPool(POOL_SIZE);
try {
for (Long messageId : messageIdList) {
MessageStatusCallable callable = new MessageStatusCallable(messageId, latch);
executorService.scheduleWithFixedDelay(
() -> {
String messageStatus = downstreamService.getMessageStatus(messageId);
if (STATUS_VALUE_SUCCEEDED.equals(messageStatus)) {
latch.countDown();
throw new CompletionException("Success - killing the task", null);
}
},
0, 100, TimeUnit.MILLISECONDS);
}
latch.await();
} finally {
executorService.shutdown();
}
}
I probably also wouldn't have the Runnable as a lambda other than for brevity in the answer.

Related

java debugging exception happenning on a Callable.call() [duplicate]

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

How to perform short-circuit evaluation in Java on two parallel threads that return boolean values?

I'm looking for guidance for a problem logically equivalent to the following:
public boolean parallelOR() {
ExecutorService executor = Executors.newFixedThreadPool(2);
Future<Boolean> taskA = executor.submit( new SlowTaskA() );
Future<Boolean> taskB = executor.submit( new SlowTaskB() );
return taskA.get() || taskB.get(); // This is not what I want
// Exception handling omitted for clarity
}
The above construction gives the correct result but always waits for taskA to complete
even if the result is already known since taskB has completed.
Is there a better construction which will allow a value to be returned
if either of the threads returns true without waiting for the second thread to complete?
(The platform involved is Android, if that affects the result).
try Using ExecutorCompletionService ... something like
ExecutorService pool = Executors.newFixedThreadPool(2);
ExecutorCompletionService<Result> completionService = new ExecutorCompletionService<Result>(pool);
completionService.submit(new SlowTaskA());
completionService.submit(new SlowTaskB());
Future<Result> future;
try {
future = completionService.take();
Result currentResult=null;
try {
currentResult = future.get();
} catch (ExecutionException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
// got the 1st result in obj currentResult, return true or obj
return true;
} catch (InterruptedException e1) {
e1.printStackTrace();
}
Here's an implementation of ParallelOr using ExecutorCompletionService. It waits on tasks until one returns true. If none do, it eventually returns false.
public class ParallelOr {
static class LongTask implements Callable<Boolean> {
private int milliseconds;
private boolean val;
public LongTask(int milliseconds, boolean val) {
this.milliseconds = milliseconds;
this.val = val;
}
#Override
public Boolean call() throws Exception {
try {
Thread.sleep(milliseconds);
} catch(Exception ex) {}
return val;
}
}
static boolean ParallelOr(List<Callable<Boolean>> tasks) {
ExecutorService pool = Executors.newFixedThreadPool(tasks.size());
ExecutorCompletionService<Boolean> completionService
= new ExecutorCompletionService<Boolean>(pool);
for(Callable<Boolean> task : tasks) {
completionService.submit(task);
}
for(int i = 0; i < tasks.size(); i++) {
try {
Future<Boolean> result = completionService.take();
if(result.get()) {
return true;
}
} catch (InterruptedException e) {
} catch (ExecutionException e) {}
}
return false;
}
public static void main(String[] args) {
ArrayList<Callable<Boolean>> tasks = new ArrayList<Callable<Boolean>>();
tasks.add(new LongTask(1000, true));
tasks.add(new LongTask(500, false));
tasks.add(new LongTask(6000, false));
boolean result = ParallelOr(tasks);
System.out.println(result);
}
}
Thanks to #Lav for pointing out the ExecutorCompleteionService class.
I think monitor logic might work nicely in this case, though it is dependent upon you being able to add alter the callables to receive a reference. It could look like this in the parallelOR() method:
ExecutorService executor = Executors.newFixedThreadPool(2);
final Object monitor = new Object();
Future<Boolean> taskA = executor.submit( new SlowTaskA(monitor) );
Future<Boolean> taskB = executor.submit( new SlowTaskB(monitor) );
Boolean ret = null,;
try {
loop:while(true){
synchronized(monitor){
monitor.wait();
}
if(taskA.isDone()){
ret = taskA.get();
if(ret.booleanValue()){
taskB.cancel(true); // If you can.
break loop;
}
}
if(taskB.isDone()){
ret = taskB.get();
if(ret.booleanValue()){
taskA.cancel(true);
break loop;
}
}
// Ifs in case of spurious wake-up
}
} catch (InterruptedException | ExecutionException e) {
e.printStackTrace();
}
While at the end of the call() method in your callables you would have:
synchronized(monitor){
monitor.notify();
}

How to stop timeout of a future

I'm computing a future for having a timeout in waiting for a serial event to happen:
Future<Response> future = executor.submit(new CommunicationTask(this, request));
response = new Response("timeout");
try {
response = future.get(timeoutMilliseconds, TimeUnit.MILLISECONDS);
} catch (InterruptedException | TimeoutException e) {
future.cancel(true);
log.info("Execution time out." + e);
} catch (ExecutionException e) {
future.cancel(true);
log.error("Encountered problem communicating with device: " + e);
}
The CommunicationTask class has implemented the Observer interface to listen to an change from the serial port.
The problem is that reading from the serial port is relatively slow and even when a serial event is happening the time runs out and a TimeoutException is thrown. What can I do to stop the timeout clock of my future when a serial event is happening?
I tried it with an AtomicReference but that didn't change anything:
public class CommunicationTask implements Callable<Response>, Observer {
private AtomicReference atomicResponse = new AtomicReference(new Response("timeout"));
private CountDownLatch latch = new CountDownLatch(1);
private SerialPort port;
CommunicationTask(SerialCommunicator communicator, Request request) {
this.communicator = communicator;
this.message = request.serialize();
this.port = communicator.getPort();
}
#Override
public Response call() throws Exception {
return query(message);
}
public Response query(String message) {
communicator.getListener().addObserver(this);
message = message + "\r\n";
try {
port.writeString(message);
} catch (Exception e) {
log.warn("Could not write to port: " + e);
communicator.disconnect();
}
try {
latch.await();
} catch (InterruptedException e) {
log.info("Execution time out.");
}
communicator.getListener().deleteObserver(this);
return (Response)atomicResponse.get();
}
#Override
public void update(Observable o, Object arg) {
atomicResponse.set((Response)arg);
latch.countDown();
}
}
What can I do to solve this problem?
EDIT:
Ok I had one error. I was counting down my latch befor setting the atomicResponse in my update function. Now it seems to work, but there's still the question if this approach is the right way to do so?
have you explored google's Guava 'future listener', it is based on Async future, hope following code snippet helps you....
import java.util.concurrent.Callable;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;
import com.google.common.util.concurrent.FutureCallback;
import com.google.common.util.concurrent.Futures;
import com.google.common.util.concurrent.ListenableFuture;
import com.google.common.util.concurrent.ListeningExecutorService;
import com.google.common.util.concurrent.MoreExecutors;
public class SyncFutureExample {
public static void main(String[] args) {
ListeningExecutorService service = MoreExecutors.listeningDecorator(Executors.newFixedThreadPool(1));
ListenableFuture<String> lf = service.submit(new CommuncationTask());
//no need for future.get() or future.get(10,time minutes)
//add callbacks(= async future listeners) ....
Futures.addCallback(lf, new FutureCallback<String>() {
public void onSuccess(String input) {
System.out.println(input + " >>> success");//gets a callback once task is success
}
public void onFailure(Throwable thrown) {
System.out.println(thrown + " >>> failure");//gets a callback if task is failed
}
});
service.shutdown();
}
}
class CommuncationTask implements Callable<String>{
public String call() throws Exception {
TimeUnit.SECONDS.sleep(15);// some dummy serious task .............
return "TaskDone";
}
}
Hope this will help. I won't comment on it in the hopes that everything is clear from the code.
class CommunicationTask implements Callable<String>, Observer {
volatile boolean ignoreTimeoutException;
public CommunicationTask(SerialCommunicator communicator, Request request) {
}
public String call() throws Exception {
Thread.sleep(1000);
return "done";
}
public void update(Observable o, Object arg) {
ignoreTimeoutException = true;
}
}
class FutureCommunicationTask extends FutureTask<String> {
private CommunicationTask ct;
public FutureCommunicationTask(CommunicationTask ct) {
super(ct);
this.ct = ct;
}
public String get(long timeout, TimeUnit unit) throws InterruptedException, ExecutionException, TimeoutException {
try {
return super.get(timeout, unit);
} catch (TimeoutException e) {
if (ct.ignoreTimeoutException) {
return get(); // no timeout wait
}
throw e;
}
}
}
public class Test {
public static void main(String[] args) throws Exception {
CommunicationTask ct = new CommunicationTask(null, null);
FutureTask<String> fct = new FutureCommunicationTask(ct);
ExecutorService ex = Executors.newSingleThreadExecutor();
ex.execute(fct);
// uncomment this line and timeout will be cancelled
ct.update(null, null);
String res = fct.get(1, TimeUnit.MILLISECONDS);
System.out.println(res);
}
}

Apply timeout control around Java operation

I'm using a third party Java library to interact with a REST API. The REST API can sometimes take a long time to respond, eventually resulting in a java.net.ConnectException being thrown.
I'd like to shorten the timeout period but have no means of modifying the third party library.
I'd like to apply some form of timeout control around the calling of a Java method so that I can determine at what point to give up waiting.
This doesn't relate directly to network timeouts. I'd like to be able to try and perform an operation and be able to give up after a specified wait time.
The following is by no means valid Java but does conceptually demonstrate what I'd like to achieve:
try {
Entity entity = new Entity();
entity.methodThatMakesUseOfRestApi();
} catch (<it's been ages now, I don't want to wait any longer>) {
throw TimeoutException();
}
I recommend TimeLimiter from Google Guava library.
This is probably the current way how this should be done with plain Java:
public String getResult(final RESTService restService, String url) throws TimeoutException {
// should be a field, not a local variable
ExecutorService threadPool = Executors.newCachedThreadPool();
// Java 8:
Callable<String> callable = () -> restService.getResult(url);
// Java 7:
// Callable<String> callable = new Callable<String>() {
// #Override
// public String call() throws Exception {
// return restService.getResult(url);
// }
// };
Future<String> future = threadPool.submit(callable);
try {
// throws a TimeoutException after 1000 ms
return future.get(1000, TimeUnit.MILLISECONDS);
} catch (ExecutionException e) {
throw new RuntimeException(e.getCause());
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
throw new TimeoutException();
}
}
There is no general timeout mechanism valid for arbitrary operations.
While... there is one... by using Thread.stop(Throwable). It works and it's thread safe, but your personal safety is in danger when the angry mob confronts you.
// realizable
try
{
setTimeout(1s); // 1
... any code // 2
cancelTimeout(); // 3
}
catch(TimeoutException te)
{
// if (3) isn't executed within 1s after (1)
// we'll get this exception
}
Now we have our nice CompletableFuture , here an application to achieve what was asked.
CompletableFuture.supplyAsync(this::foo).get(15, TimeUnit.SECONDS)
You could use a Timer and a TimerTask.
Here's a utility class I wrote, which should do the trick unless I've missed something. Unfortunately it can only return generic Objects and throw generic Exceptions. Others may have better ideas on how to achieve this.
public abstract class TimeoutOperation {
long timeOut = -1;
String name = "Timeout Operation";
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public long getTimeOut() {
return timeOut;
}
public void setTimeOut(long timeOut) {
this.timeOut = timeOut;
}
public TimeoutOperation (String name, long timeout) {
this.timeOut = timeout;
}
private Throwable throwable;
private Object result;
private long startTime;
public Object run () throws TimeoutException, Exception {
Thread operationThread = new Thread (getName()) {
public void run () {
try {
result = doOperation();
} catch (Exception ex) {
throwable = ex;
} catch (Throwable uncaught) {
throwable = uncaught;
}
synchronized (TimeoutOperation.this) {
TimeoutOperation.this.notifyAll();
}
}
public synchronized void start() {
super.start();
}
};
operationThread.start();
startTime = System.currentTimeMillis();
synchronized (this) {
while (operationThread.isAlive() && (getTimeOut() == -1 || System.currentTimeMillis() < startTime + getTimeOut())) {
try {
wait (1000L);
} catch (InterruptedException ex) {}
}
}
if (throwable != null) {
if (throwable instanceof Exception) {
throw (Exception) throwable;
} else if (throwable instanceof Error) {
throw (Error) throwable;
}
}
if (result != null) {
return result;
}
if (System.currentTimeMillis() > startTime + getTimeOut()) {
throw new TimeoutException("Operation '"+getName()+"' timed out after "+getTimeOut()+" ms");
} else {
throw new Exception ("No result, no exception, and no timeout!");
}
}
public abstract Object doOperation () throws Exception;
public static void main (String [] args) throws Throwable {
Object o = new TimeoutOperation("Test timeout", 4900) {
public Object doOperation() throws Exception {
try {
Thread.sleep (5000L);
} catch (InterruptedException ex) {}
return "OK";
}
}.run();
System.out.println(o);
}
}
static final int NUM_TRIES =4;
int tried =0;
boolean result =false;
while (tried < NUM_TRIES && !result)
{
try {
Entity entity = new Entity();
result = entity.methodThatMakesUseOfRestApi();
}
catch (<it's been ages now, I don't want to wait any longer>) {
if ( tried == NUM_TRIES)
{
throw new TimeoutException();
}
}
tried++;
Thread.sleep(4000);
}

Handling Exceptions for ThreadPoolExecutor

I have the following code snippet that basically scans through the list of task that needs to be executed and each task is then given to the executor for execution.
The JobExecutor in turn creates another executor (for doing db stuff...reading and writing data to queue) and completes the task.
JobExecutor returns a Future<Boolean> for the tasks submitted. When one of the task fails, I want to gracefully interrupt all the threads and shutdown the executor by catching all the exceptions. What changes do I need to do?
public class DataMovingClass {
private static final AtomicInteger uniqueId = new AtomicInteger(0);
private static final ThreadLocal<Integer> uniqueNumber = new IDGenerator();
ThreadPoolExecutor threadPoolExecutor = null ;
private List<Source> sources = new ArrayList<Source>();
private static class IDGenerator extends ThreadLocal<Integer> {
#Override
public Integer get() {
return uniqueId.incrementAndGet();
}
}
public void init(){
// load sources list
}
public boolean execute() {
boolean succcess = true ;
threadPoolExecutor = new ThreadPoolExecutor(10,10,
10, TimeUnit.SECONDS, new ArrayBlockingQueue<Runnable>(1024),
new ThreadFactory() {
public Thread newThread(Runnable r) {
Thread t = new Thread(r);
t.setName("DataMigration-" + uniqueNumber.get());
return t;
}// End method
}, new ThreadPoolExecutor.CallerRunsPolicy());
List<Future<Boolean>> result = new ArrayList<Future<Boolean>>();
for (Source source : sources) {
result.add(threadPoolExecutor.submit(new JobExecutor(source)));
}
for (Future<Boolean> jobDone : result) {
try {
if (!jobDone.get(100000, TimeUnit.SECONDS) && success) {
// in case of successful DbWriterClass, we don't need to change
// it.
success = false;
}
} catch (Exception ex) {
// handle exceptions
}
}
}
public class JobExecutor implements Callable<Boolean> {
private ThreadPoolExecutor threadPoolExecutor ;
Source jobSource ;
public SourceJobExecutor(Source source) {
this.jobSource = source;
threadPoolExecutor = new ThreadPoolExecutor(10,10,10, TimeUnit.SECONDS, new ArrayBlockingQueue<Runnable>(1024),
new ThreadFactory() {
public Thread newThread(Runnable r) {
Thread t = new Thread(r);
t.setName("Job Executor-" + uniqueNumber.get());
return t;
}// End method
}, new ThreadPoolExecutor.CallerRunsPolicy());
}
public Boolean call() throws Exception {
boolean status = true ;
System.out.println("Starting Job = " + jobSource.getName());
try {
// do the specified task ;
}catch (InterruptedException intrEx) {
logger.warn("InterruptedException", intrEx);
status = false ;
} catch(Exception e) {
logger.fatal("Exception occurred while executing task "+jobSource.getName(),e);
status = false ;
}
System.out.println("Ending Job = " + jobSource.getName());
return status ;
}
}
}
When you submit a task to the executor, it returns you a FutureTask instance.
FutureTask.get() will re-throw any exception thrown by the task as an ExecutorException.
So when you iterate through the List<Future> and call get on each, catch ExecutorException and invoke an orderly shutdown.
Since you are submitting tasks to ThreadPoolExecutor, the exceptions are getting swallowed by FutureTask.
Have a look at this code
**Inside FutureTask$Sync**
void innerRun() {
if (!compareAndSetState(READY, RUNNING))
return;
runner = Thread.currentThread();
if (getState() == RUNNING) { // recheck after setting thread
V result;
try {
result = callable.call();
} catch (Throwable ex) {
setException(ex);
return;
}
set(result);
} else {
releaseShared(0); // cancel
}
}
protected void setException(Throwable t) {
sync.innerSetException(t);
}
From above code, it is clear that setException method catching Throwable. Due to this reason, FutureTask is swallowing all exceptions if you use "submit()" method on ThreadPoolExecutor
As per java documentation, you can extend afterExecute() method in ThreadPoolExecutor
protected void afterExecute(Runnable r,
Throwable t)
Sample code as per documentation:
class ExtendedExecutor extends ThreadPoolExecutor {
// ...
protected void afterExecute(Runnable r, Throwable t) {
super.afterExecute(r, t);
if (t == null && r instanceof Future<?>) {
try {
Object result = ((Future<?>) r).get();
} catch (CancellationException ce) {
t = ce;
} catch (ExecutionException ee) {
t = ee.getCause();
} catch (InterruptedException ie) {
Thread.currentThread().interrupt(); // ignore/reset
}
}
if (t != null)
System.out.println(t);
}
}
You can catch Exceptions in three ways
Future.get() as suggested in accepted answer
wrap entire run() or call() method in try{}catch{}Exceptoion{} blocks
override afterExecute of ThreadPoolExecutor method as shown above
To gracefully interrupt other Threads, have a look at below SE question:
How to stop next thread from running in a ScheduledThreadPoolExecutor
How to forcefully shutdown java ExecutorService
Subclass ThreadPoolExecutor and override its protected afterExecute (Runnable r, Throwable t) method.
If you're creating a thread pool via the java.util.concurrent.Executors convenience class (which you're not), take at look at its source to see how it's invoking ThreadPoolExecutor.

Categories

Resources