how can i handle CancellationException in java concurrent programming? - java

I am using java.util.concurrent package to create a parallel program. I have 2 threads:
thread-1 which invokes webservice method-1, and
thread-2 which invokes webservice method-2.
I am specifying a thread execution timeout - suppose if thread-1 does not complete execution within the specified timeout then I have to intercept thread-1, continue the execution with thread-2 and display thread-2 results in jsp (note: if both threads take too much time to process the requests then I don't want the UI to wait until they complete).
I tried with the code below but it throws an InterruptedException. How can I proceed with other tasks when one task takes more mire?
ExecutorService executor = Executors.newFixedThreadPool(2);
CompletionService<ArrayList<AvailableWeatherDetailVO>> compService = new ExecutorCompletionService<ArrayList<AvailableWeatherDetailVO>>(executor);
// Start amazonTask using thread-1
try{
compService.submit(amazonTask).get(20, TimeUnit.MILLISECONDS);
amazonFuture = compService.take();
amazonFinalList =(ArrayList<AvailableWeatherDetailVO>)amazonFuture .get() }
catch (TimeoutException e) {
compService.submit(amazonTask).cancel(true);
//throw new TimeoutException("Thread not executed with in speifed time");
}
// Start googleTask using thread-2
try{
compService.submit(googleTask).get(100, TimeUnit.MILLISECONDS);
googleFuture = compService.take();
googleFinalList =(ArrayList<AvailableWeatherDetailVO>)googleFuture .get() }
catch (TimeoutException e) {
compService.submit(googleTask).cancel(true);
//throw new TimeoutException("Thread not executed with in speifed time");
}

It is not clear if you mean thread2 only begins execution if thread1 fails.
Or, are they both executing, but you want to use the result of thread1 if it completes, else you want to use the result of thread2
It sounds to me like you should attach thread 1 to a Future. Then get the result (from your main thread) with a timeout. If the Future.get() times out, then get the result from the second thread.
Not sure if I got your meaning. If this is not what you are looking for, please clarify.

Related

Exception Handling ScheduledExecutorService

I am using ScheduledExecutorService to run threads at a fixed interval of 1 min.
One instance of ScheduledExecutorService runs one thread and another instance runs another thread.
Example:
ses1.scheduleAtFixRate(..) // for thread 1
ses2.scheduleAtFixRate(..) // for thread 2
I was encountering some exceptions by which the further execution stops. I want to catch the exception for a systematic shutdown of my application.
Should I handle the exception using a third thread that monitors both futures and handles the Exception or is there any other better way? Will it affect the other threads.
Any and all help is appreciated!
I was encountering some exceptions by which the further execution
stops.
That is the expected behavior of ScheduledExecutorService.scheduleAtFixRate() according to the specification :
If any execution of the task encounters an exception, subsequent
executions are suppressed.
About your need :
I want to catch the exception for a systematic shutdown of my
application.
Should I handle the exception using a third thread that monitors both
futures and handles the Exception or is there any other better way?
Handling the future return with ScheduledFuture.get() looks the right.
According to ScheduledFuture.scheduleAtFixedRate() specification :
Otherwise, the task will only terminate via cancellation or
termination of the executor.
So you don't even need to create a new scheduled future.
Just run two parallel tasks (with ExecutorService or two threads is also possible) that wait on get() of each Future and that stops the application in case of exception thrown in the task :
Future<?> futureA = ses1.scheduleAtFixRate(..) // for thread 1
Future<?> futureB = ses2.scheduleAtFixRate(..) // for thread 2
submitAndStopTheApplicationIfFail(futureA);
submitAndStopTheApplicationIfFail(futureB);
public void submitAndStopTheApplicationIfFail(Future<?> future){
executor.submit(() -> {
try {
future.get();
} catch (InterruptedException e) {
// stop the application
} catch (ExecutionException e) {
// stop the application
}
});
}

How to use CompletableFuture in java 8 to start an async task and let main thread finish and exit

I have the following code (more or less):
ExecutorService executor = Executors.newFixedThreadPool(10);
CompletableFuture
.supplyAsync(()->{
return longRunningMethodThatReturnsBoolean();
}, executor)
.thenAcceptAsync(taskResult -> {
logResult();
executor.shutdown();
}, executor);
This allows the code in the main thread to continue, however I was expecting the main thread to die when it finished and the future to keep working in it's own thread, but the main thread stays alive until the CompletableFuture finishes even though the main thread isn't doing anything anymore.
I'm kind of new to this, am I missing something? Is it even possible?
Any help will be greatly appreciated!!!
Actually, if your main thread doesn't wait on the CompletableFuture's .get() or any other blocking method, then it dies as soon as it reaches the end of the main method.
You can check it using the following example:
public static void main(String[] args){
final Thread mainThread = Thread.currentThread();
ExecutorService executor = Executors.newFixedThreadPool(10);
CompletableFuture
.supplyAsync(()-> {
try {
Thread.sleep(1000);
//prints false
System.out.println("Main thread is alive: " + mainThread.isAlive());
Thread.sleep(3000);
} catch (InterruptedException e) {
e.printStackTrace();
}
return true;
}, executor)
.thenAcceptAsync(taskResult -> {
System.out.println("LongRunning is finished");
executor.shutdown();
}, executor);
}
But the Java Virtual Machine continues to execute threads until either of the following occurs
The exit method of class Runtime has been called and the security manager has permitted the exit operation to take place.
All threads that are not daemon threads have died, either by returning from the call to the run method or by throwing an exception
that propagates beyond the run method.
It means that even though the main thread is dead, the virtual machine continues to work because all threads created by the Executors.newFixedThreadPool(10) are non-daemon. You can read about it in the documentation of the defaultThreadFactory() method in the Executors class:
Each new thread is created as a non-daemon thread with priority set to
the smaller of Thread.NORM_PRIORITY and the maximum priority permitted
in the thread group
The main thread waits until all the other non-daemon threads are done before cleaning up and exiting the process:
http://hg.openjdk.java.net/jdk7/jdk7/hotspot/file/9b0ca45cd756/src/share/vm/runtime/thread.cpp#l3629

How to be sure threads are cleaned up

I have a method producer.postMessage(message) which sends a message to some queue. If for some reason the message could not be sent in a period of time I want this task to be canceled. I came up with the implementation below. My question is if there is an interrupt can I be sure the Future task/ executor service are all shutdown and if not what changes need to be made to make this working without any threads not being terminated.
Thanks a lot
public void postMessage(final Object object)
{
LOG.debug("postMessage object " + object.getClass().getSimpleName());
Message message = new Message("task", 10, object);
try
{
ExecutorService ex = Executors.newSingleThreadExecutor();
Future<?> f = ex.submit(new Runnable()
{
public void run()
{
producer.postMessage(message);
LOG.debug("Finished sending message for " + object.getClass().getSimpleName());
}
});
f.get(5, TimeUnit.SECONDS);
ex.shutdown();
}
catch (InterruptedException | ExecutionException | TimeoutException e)
{
LOG.error("Could not deliver message to the queue, Check AMQ is running");
}
}
The shutdown() method on an Executor will stop it from accepting new tasks, but attempts to complete the running tasks. You should use method shutdownNow() to have the Executor request that currently running tasks are stopped.
This may not be necessary however, if you use method cancel(boolean mayInterruptIfRunning) on the Future object. f.get(5, TimeUnit.SECONDS) will wait at most 5 seconds for completion of the tasks before returning. Since you submit a Runnable rather than a Callable, the return will always be null; Runnables can't return a result, while Callables can. What you can do is call isDone() on the Future after the get with a 5 second timeout, and if it returns false, it means the tasks has not completed. In that case you can then call cancel(true) on the Future to attempt to cancel the task. The true argument indicates that you'll allow the Future to interrupt the thread if it is running. You may want to catch InterruptedExceptions in your Runnable and log them. Note however that not every call may respond to interrupt requests (for example, some I/O operations may not, while a lot of Java NIO stuff does).
Calling the shutdown on the executor may no longer be necessary, since it's only used for a single task and should have no other waiting or running tasks, but it's probably still good form.
So your code would become:
f.get(5, TimeUnit.SECONDS);
if (!f.isDone())
f.cancel(true);
ex.shutdown();

Why does the program wait for the schedule() to finish but doesn't wait for the scheduleWithFixedDelay()?

Here's the code:
ScheduledExecutorService service = null;
try {
service = Executors.newSingleThreadScheduledExecutor();
Runnable task1 = () -> System.out.println("Executed only once");
Runnable task2 = () -> System.out.println("Executed repeatedly");
service.schedule(task1, 5, TimeUnit.SECONDS);
service.scheduleWithFixedDelay(task2, 6, 2, TimeUnit.SECONDS);
} finally {
if (service != null) {
service.shutdown();
}
}
When executing the above code the program waits 5 seconds to run schedule() but after that it finishes without running the scheduleWithFixedDelay().
I suspect the reason is that schedule() is executed synchronously unlike the scheduleWithFixedDelay() but I haven't found the arguments in favor of this in the docs.
This is a bit subtle, but I think the answer lies in the wording of the documentation for shutdown:
Initiates an orderly shutdown in which previously submitted tasks are executed, but no new tasks will be accepted.
Your first task qualifies as a “previously submitted task,” so shutdown() waits for it to execute.
Technically, the repeating task was previously submitted, but since it repeats forever, waiting for it complete is impossible. Attempting to do so would violate the contract of shutdown(). So, I would say that the only alternative is to ignore future executions of repeating tasks.

Wait for task to finish before terminating in ScheduledThreadPoolExecutor

I have a Runnable implementation that does some work which might take some time and I am trying to schedule it using ScheduledThreadPoolExecutorwith scheduleAtFixedRate method. Now I want to ensure that shut down is graceful that means, Before terminating, task should be allowed to run completely. I have written following code for shutdown.
public void shutDown() throws Exception {
try {
LOG.info("Gracefully shutting down executor");
executor.shutdown();
if (!executor.awaitTermination(SHUTDOWN_TIMEOUT, TimeUnit.SECONDS)) {
// cancels currently executing tasks.
LOG.info("Executor is still alive. Forcing executor thread pool to shut down");
executor.shutdownNow();
// Wait a while for tasks to respond to being cancelled
if (!executor.awaitTermination(SHUTDOWN_TIMEOUT, TimeUnit.SECONDS)) {
LOG.fatal("Executor thread pool did not terminate");
throw new Exception("Unable to shut down executor thread pool forcefully");
}
LOG.info("Executor shut down.");
}
} catch (Exception e) {
LOG.error("Exception shutting down executor", e);
throw e;
}
}
But problem with this is, I have to specify time to wait explicitly and I can not predict time taken by task in advance. Is there a way to make executor wait indefinitely until executing task finishes without having to mention time to wait? Or is there a better way to work on above scenario?
Thanks
Jitendra
Simplest solution is to "overprovision" so to speak. I suggest you use a huge timeout period that in no way can be exceeded by the time needed for a single task to execute, like:
// do you have tasks that can take more than 2^63 - 1 days to finish? :)
executor.awaitTermination(Long.MAX_VALUE, TimeUnit.DAYS);
Use shutdown() to begin a graceful termination, and then use awaitTermination(long, TimeUnit) to wait for the executor service to finish shutting down.
As it was noted in the comment executor.shutdown() is not forcing any tasks to exit but rather it prevents new ones from being accepted. Have a look in the javadoc.
Another advice is if you want to get hold of your tasks as soon as they complete, you can implement Callable<T> instead of a Runnable that it's of a generic type and returns a value of type T. Then you can wrap this Callable<T> into a FutureTask<V> and submit that to your ScheduledThreadPoolExecutor. You can then loop through your tasks as soon as they have completed their work and are available. So in short something like this (notice as soon as we are done loading the scheduler with tasks it's safe to shut it down meaning that we don't allow any further tasks to be submitted from then on):
ScheduledExecutorService schedulerExecutor = Executors.newScheduledThreadPool(n);
Callable<Integer> myTask = . . .;
FutureTask<Integer> task = new FutureTask<Integer>(myTask);
schedulerExecutor.scheduleAtFixedRate(task, 0, 1, TimeUnit.SECONDS);
schedulerExecutor.shutdown();

Categories

Resources