InterruptedException thrown from futures - java

Suppose I have a method as follows:
public void poll(Callable<Boolean> callable) {
ScheduledExecutorService service = Executors.newSingleThreadedScheduledExecutor();
Future<Boolean> future = service.schedule(callable, 0L, TimeUnit.MILLISECONDS);
try {
while (!future.get()) {
future = service.schedule(callable, 5L, TimeUnit.MINUTES);
}
} catch (ExecutionException e) {
// ...
} catch (InterruptedException e) {
// ...
} finally {
service.shutdown();
}
}
How does an InterruptedException ever get thrown (and caught in poll())? Anything thrown by the callable (including InterruptedException, right?) would be an ExecutionException, we never cancel any futures, and the service's shutdownNow() is never called.
Aside: being what it is, is it possible to make this polling method more bulletproof against things like InterruptedException?

The InterruptedException would be thrown by get while waiting (blocking) for the callable to finish.
I'm not sure what you mean by bulletproof, you have to handle the possibility of the exception being thrown.

InterruptedException can be thrown by the thread which called get and is waiting for completion, not by the callable

Related

Use CompletableFuture to execute single or multiple Callables and avoid blocking

I execute a few callables through ThreadPoolExecutor. If thread list contains only 1 callable then I directly call call method of my CallableService. If list contains more than 1 callables then I execute all those threads in parallel via thread pool executor.
How can I achieve this with Java 8 CompletableFuture? And if future.get() is enhanced to avoid blocking, that will be a plus.
private static ThreadPoolExecutor myThreadPoolExecutor = new ThreadPoolExecutor(0, 100, 5L, TimeUnit.SECONDS, new SynchronousQueue<>());
public static void execute(List<Callable<Boolean>> threadList) throws Exception {
List<Future<Boolean>> futureList = null;
CallableService singleService = (CallableService) threadList.get(0);
if (1 == threadList.size()) {
singleService.call();
}
else {
try {
futureList = myThreadPoolExecutor.invokeAll(threadList);
}
catch (InterruptedException e) {
e.printStackTrace();
}
}
if (null != futureList) {
for (Future<Boolean> future : futureList) {
try {
future.get();
}
catch (Exception e) {
//do some calculations here and then throw exception
throw new Exception(e.getMessage(), e);
}
}
}
}
There is no need for CompletableFuture, as the way you use the ExecutorService is sufficient, though, there are some aspects of the code flow which could be improved. You fetch the first element, even when not needed, and you cast it to CallableService for no reason, as you can call the method via the Callable interface already. In the other branch you are catching InterruptedException and proceeding, so the caller would never know that not all jobs have been executed. And in a straight-forward code flow, you don't need to check the list for null:
public static void execute(List<Callable<Boolean>> threadList) throws Exception {
if(1 == threadList.size()) {
Callable<Boolean> singleService = threadList.get(0);
singleService.call();
}
else {
List<Future<Boolean>> futureList = myThreadPoolExecutor.invokeAll(threadList);
for(Future<Boolean> future : futureList) {
try {
future.get();
}
catch(Exception e) {
//do some calculations here and then throw exception
throw new Exception(e.getMessage(), e);
}
}
}
}
You could shorten it further to
public static void execute(List<Callable<Boolean>> threadList) throws Exception {
if(1 == threadList.size()) {
threadList.get(0).call();
}
else {
for(Future<Boolean> future : myThreadPoolExecutor.invokeAll(threadList)) {
try {
future.get();
}
catch(Exception e) {
//do some calculations here and then throw exception
throw new Exception(e.getMessage(), e);
}
}
}
}
But that's a matter of preferred coding style. But note that it caught my eye that in the single element case, you're not performing the same exception handling.
To use CompletableFuture, we need an adapter method, as the convenience method supplyAsync requires a Supplier instead of a Callable. Using a modified variant of this answer, we get
public static void execute(List<Callable<Boolean>> threadList) throws Exception {
if(1 == threadList.size()) {
threadList.get(0).call();
}
else {
CompletableFuture<?> all = CompletableFuture.allOf(
threadList.stream()
.map(c -> callAsync(c, myThreadPoolExecutor))
.toArray(CompletableFuture<?>[]::new));
try {
all.get();
}
catch(Exception e) {
//do some calculations here and then throw exception
throw new Exception(e.getMessage(), e);
}
}
}
public static <R> CompletableFuture<R> callAsync(Callable<R> callable, Executor e) {
CompletableFuture<R> cf = new CompletableFuture<>();
CompletableFuture.runAsync(() -> {
try { cf.complete(callable.call()); }
catch(Throwable ex) { cf.completeExceptionally(ex); }
}, e);
return cf;
}
So we have no invokeAll which takes care of submitting all jobs. We have to do this manually, either with a loop or a stream operation. On the other hand, we get a single future via allOf representing the completion status, exceptionally if at least one job failed.
Unlike invokeAll, which waits for the completion, allOf only returns the future so it is the all.get() call which waits for the completion. We could do other things before it or even use this property to always perform the first job in the caller thread:
public static void execute(List<Callable<Boolean>> threadList) throws Exception {
CompletableFuture<?> tail = CompletableFuture.allOf(
threadList.stream().skip(1)
.map(c -> callAsync(c, myThreadPoolExecutor))
.toArray(CompletableFuture<?>[]::new)),
head = callAsync(threadList.get(0), Runnable::run);
try {
head.get();
tail.get();
}
catch(Exception e) {
//do some calculations here and then throw exception
throw new Exception(e.getMessage(), e);
}
}
This will always call the first callable in the current thread, as Runnable::run used as Executor will perform the action immediately in the calling thread. But it's treated uniformly in all other aspects, especially the exception handling. When there is only one job, allOf invoke with an empty array will do nothing and return an already completed future, which will have the desired effect.
Future.isDone() tells us if the executor has finished processing the task. If the task is completed, it will return true otherwise, it returns false.
for (Future<Boolean> future : futureList) {
while(!future.isDone())
{
doSOmethingElse();
Thread.sleep(300);//Optional
}
try {
future.get();
}
catch (Exception e)
{
//do some calculations here and then throw exception
throw new Exception(e.getMessage(), e);
}
}
But we don't have to worry about that since we get to the point where get() is called after making sure that the task is finished.
I execute a few callables through ThreadPoolExecutor. If thread list contains only 1 callable then I directly call call method of my CallableService. If list contains more than 1 callables then I execute all those threads in parallel via thread pool executor.
I guess you have already implemented this part. (You might run into memory usage issues if your jobs are heavy and you have 100 threads running as configured. But that is a different problem.)
And if future.get() is enhanced to avoid blocking, that will be a plus.
For this, you may take this approach:
Create another ExecutorService whose job will be just to run the Future.get() calls.
Submit your Future.get() to that service as shown below.
Shut it down and await termination.
if (null != futureList) {
ExecutorService waitSvc = Executors.newCachedThreadPool();
for (Future<Boolean> future : futureList) {
try {
waitSvc.submit( () -> future.get() );
}
catch (Exception e) {
//do some calculations here and then throw exception
throw new Exception(e.getMessage(), e);
}
}
waitSvc.shutdown(); //This may take some time. You may want to call awaitTermination() after this.
}
However, I feel that you should redesign the overall approach of using so many threads, unless this is only a for-learning application.

Why is my sleeping thread not being interrupted?

I want to interrupt a sleeping thread, but it throws InterruptedException and doesn't stop. When I put Thread.interrupt() to the catch block, it interrupts the thread, but not from the first try.
I have a message, which must be written to file, when the thread is interrupted, but it write this message about 4-5 times. So I understand that thread is not interrupted at once. Why is it so, and what do I have to do?
My code has variable count of threads which changes at run-time. Each thread call method printAndDelay, which makes record to file and sleep. But I must have opportunity to stop any thread in any moment from main thread and record reason of stop to the same file.
void printAndDelay(String message, int delay)
{
try {
writeToLogFile(message, logFileName);
Thread.sleep(delay);
}
catch (InterruptedException e)
{
writeToLogFile("The reason of cancelling", logFileName);
Thread.currentThread().interrupt();
}
}
I try to interrupt thread by this code:
void stopOrder(String threadName)
{
Map<Thread, StackTraceElement[]> threads = Thread.getAllStackTraces();
threads.keySet().stream()
.filter(k -> k.getName().equalsIgnoreCase(threadName))
.findFirst()
.get()
.interrupt();
}
and I see that I can find this thread, but it throws InterruptException but doesn't stop thread. So I tried to stop it by putting Thread.interrupt() into the catch block.
For the message to be printed 4-5 times, you presumably have some loop which is calling printAndDelay multiple times:
for (Object obj : someList)
{
printAndDelay("hello", 1000);
}
Rather than dealing with the exception within printAndDelay, declare it as thrown in the method signature and deal with it from where the method is called.
void printAndDelay(String message, int delay) throws InterruptedException
{
writeToLogFile(message, logFileName);
Thread.sleep(delay);
}
You would alter your loop like so:
try
{
for (Object obj : someList)
{
printAndDelay("hello", 1000);
}
}
catch (final InterruptedException e)
{
writeToLogFile("The reason of cancelling", logFileName);
}
If "the reason of cancelling" is not a constant, you may want to wrap the InterruptedException in some other exception type, possibly a custom one, to pass the message upwards.
You need to do it like this. Stop the execution of the thread by throwing the InterruptedException.
void printAndDelay(String message, int delay) throws InterruptedException {
try {
writeToLogFile(message, logFileName);
Thread.sleep(delay);
} catch (InterruptedException e) {
writeToLogFile("The reason of cancelling", logFileName);
// propagate the exception
throw e;
}
}
And in the run method you need to restore the interrupt status.
public void run() {
try {
// whatever you want to do
printAndDelay(.....
}
catch (InterruptedException e) {
// Restore the interrupted status
Thread.currentThread().interrupt();
}
}
The reason why I throw the InterruptedException and don't wrap it in another exception is that I want to restore the interrupt of the thread in the run method. You can even restore the interrupt right in the method and then throw some custom exception or a RuntimeException and stop the execution of your thread.

future.cancel does not work

I have a nice and compact code, which does not work as I expected.
public class Test {
public static void main(String[] args) {
Runnable r = new Runnable() {
#Override
public void run() {
try {
for (;;) {
}
} finally {
System.out.println("FINALLY");
}
}
};
ExecutorService executor = Executors.newSingleThreadExecutor();
Future<?> future = executor.submit(r);
try {
future.get(3, TimeUnit.SECONDS);
} catch (TimeoutException e) {
boolean c = future.cancel(true);
System.out.println("Timeout " + c);
} catch (InterruptedException | ExecutionException e) {
System.out.println("interrupted");
}
System.out.println("END");
}
}
The output is :
Timeout true
END
Question:
Why does not terminate the future.cancel(true) method the called Runnable?
After the program wrote the "END" to the output, the "r" Runnable is still running.
The problem is that your Runnable is not interruptible: task interruption is a collaborative process in Java and the cancelled code needs to check regularly if it's been cancelled, otherwise it won't respond to the interruption.
You can amend you code as follows and it should work as expected:
Runnable r = new Runnable() {
#Override public void run() {
try {
while (!Thread.currentThread().isInterrupted()) {}
} finally {
System.out.println("FINALLY");
}
}
};
This is always a little bit misleading: The ExceutorService or even the underlying thread scheduler do not know anything about what the Runnable is doing. In your case they don't know that there is a unconditional loop.
All these methods (cancel, done, ...) are related to manage Threads in the Executor structure. cancel cancels the thread from the point of view of the Executor service.
The programmer must test if the Runnable was canceled and must terminate the run() method.
So in your case (if I remember well) something like this:
public class Test {
public static void main(String[] args) {
FutureTask r = new FutureTask () {
#Override
public void run() {
try {
for (;!isCancelled();) {
}
} finally {
System.out.println("FINALLY");
}
}
};
ExecutorService executor = Executors.newSingleThreadExecutor();
Future<?> future = executor.submit(r);
try {
future.get(3, TimeUnit.SECONDS);
} catch (TimeoutException e) {
boolean c = future.cancel(true);
System.out.println("Timeout " + c);
} catch (InterruptedException | ExecutionException e) {
System.out.println("interrupted");
}
System.out.println("END");
}
}
When you cancel a Future whose Runnable has already begun, the interrupt method is called on the Thread that is running the Runnable. But that won't necessarily stop the thread. Indeed, if it's stuck in a tight loop, like the one you've got here, the Thread won't stop. In this case, the interrupt method just sets a flag called the "interrupt status", which tells the thread to stop when it can.
See the Javadoc for the interrupt method of Thread
Future.cancel() will cancel any queued task or will call Thread.interrupt() on your thread if already running.
You need to interrupt your code
It's your code's responsibility is to be ready for any interruptions. I'd go so far to say that whenever you have a long running task, that you insert some interrupt ready code like this:
while (... something long...) {
... do something long
if (Thread.interrupted()) {
... stop doing what I'm doing...
}
}
How to stop what I'm doing?
You have several options:
If your you are in Runnable.run() just return or break out of the loop and finish the method.
You may be in some other method deep in the code. It may make sense at that point for that method to throw InterruptedException so you would just do that (leaving the flag cleared).
But maybe deep in your code it doesn't make sense to throw InterruptedException. In that case you should throw some other exception, but before that mark your thread interrupted again so the code that catches knows that an interrupt was in progress. Here's an example:
private void someMethodDeepDown() {
while (.. long running task .. ) {
... do lots of work ...
if (Thread.interrupted()) {
// oh no! an interrupt!
Thread.currentThread().interrupt();
throw new SomeOtherException();
}
}
}
Now the exception can propagate an either terminate the thread or be caught, but the receiving code hopefully notices that an interrupt is in progress.

setting interrupt bit does not make Future.get() throw TimeoutException

Why doesn't setting the interrupt bit in a Callable cause the Future that represents the Callable to throw a TimeoutException when Future.get() is called?
public class ExecutorServiceTest extends MockitoTestCase {
private static CountDownLatch latch1 = new CountDownLatch(1);
class TaskChecksForInterruptedExcAndDoesSetInterruptedBit implements Callable<String> {
#Override
public String call() {
latch1.countDown();
while (!Thread.currentThread().isInterrupted()) {
}
Thread.currentThread().interrupt();
return "blah";
}
}
void testInterrupt() throws Exception {
ExecutorService pool = Executors.newFixedThreadPool(numThreads);
Future<String> future = pool.submit(new TaskChecksForInterruptedExcAndDoesSetInterruptedBit());
latch1.await(); // Don't interrupt the Callable until it actually starts processing
pool.shutdownNow();
try {
future.get(100, TimeUnit.MILLISECONDS);
} catch (final TimeoutException e) {
// Why doesn't this get called!
return;
}
fail();
}
}
the shutdownNow() call attempts to interrupt all running tasks. In this case the interruption is detected in your busy loop, so the code continues and the Callable returns "blah" (and not an exception)
TimeoutException, according to the spec, is thrown only if the thread waits for the complete timeout period, but no result becomes available. Interruption doesn't fit into this scenario.
Your usage of CountDownLatch is incorrect. You decrement it, but I see no call to latch1.await()

In what cases does Future.get() throw ExecutionException or InterruptedException

My code snippet:
ExecutorService executor = Executors.newSingleThreadExecutor();
try {
Task t = new Task(response,inputToPass,pTypes,unit.getInstance(),methodName,unit.getUnitKey());
Future<SCCallOutResponse> fut = executor.submit(t);
response = fut.get(unit.getTimeOut(),TimeUnit.MILLISECONDS);
} catch (TimeoutException e) {
// if the task is still running, a TimeOutException will occur while fut.get()
cat.error("Unit " + unit.getUnitKey() + " Timed Out");
response.setVote(SCCallOutConsts.TIMEOUT);
} catch (InterruptedException e) {
cat.error(e);
} catch (ExecutionException e) {
cat.error(e);
} finally {
executor.shutdown();
}
How should i handle the InterruptedException and ExecutionException in the code?
And in what cases, are these exceptions thrown?
ExecutionException and InterruptedException are two very different things.
ExecutionException wraps whatever exception the thread being executed threw, so if your thread was, for instance, doing some kind of IO that caused an IOException to get thrown, that would get wrapped in an ExecutionException and rethrown.
An InterruptedException is not a sign of anything having gone wrong. It is there to give you a way to let your threads know when it's time to stop so that they can finish up their current work and exit gracefully. Say I want my application to stop running, but I don't want my threads to drop what they're doing in the middle of something (which is what would happen if I made them daemon threads). So when the application is being shutdown, my code calls the interrupt method on these threads, which sets the interrupt flag on them, and the next time those threads are waiting or sleeping they check the interrupt flag and throw an InterruptedException, which I can use to bail out of whatever infinite-loop processing/sleeping logic the threads are engaged in. (And if the thread doesn't wait or sleep, it can just check the interrupt flag periodically.) So it is an instance of an exception being used to change the logical flow. The only reason you would log it at all is in an example program to show you what's happening, or if you're debugging a problem where interrupt logic is not working correctly.
InterruptedException will be thrown if interrupt is called on the waiting thread before the computation has completed.
ExecutionException will be thrown if the computation involved (Task in this case) throws an exception itself.
How you want to handle this will entirely depend on your application.
EDIT: Here's a demonstration of being interrupted:
import java.util.concurrent.*;
public class Test
{
public static void main(String[] args) throws Exception
{
ExecutorService executor = Executors.newFixedThreadPool(2);
Future<String> future = executor.submit(new SlowCallable());
executor.submit(new Interruptor(Thread.currentThread()));
try
{
System.out.println(future.get());
}
catch (InterruptedException e)
{
System.out.println("I was interrupted");
}
}
private static class Interruptor implements Callable<String>
{
private final Thread threadToInterrupt;
Interruptor(Thread threadToInterrupt)
{
this.threadToInterrupt = threadToInterrupt;
}
public String call() throws Exception
{
Thread.sleep(2000);
threadToInterrupt.interrupt();
return "interrupted other thread";
}
}
private static class SlowCallable implements Callable<String>
{
public String call() throws Exception
{
Thread.sleep(5000);
return "finished";
}
}
}
Sample code to return three types of Exceptions.
import java.util.concurrent.*;
import java.util.*;
public class ExceptionDemo{
public static void main(String args[]){
int poolSize=1;
int maxPoolSize=1;
int queueSize=30;
long aliveTive=60;
ArrayBlockingQueue<Runnable> queue= new ArrayBlockingQueue<Runnable>(queueSize);
ThreadPoolExecutor executor= new ThreadPoolExecutor(poolSize,maxPoolSize,aliveTive,
TimeUnit.MILLISECONDS,queue);
List<Future> futures = new ArrayList<Future>();
for ( int i=0; i < 5; i++){
futures.add(executor.submit(new RunnableEx()));
}
for ( Iterator it = futures.iterator(); it.hasNext();){
try {
Future f = (Future)it.next();
f.get(4000,TimeUnit.MILLISECONDS);
}catch(TimeoutException terr){
System.out.println("Timeout exception");
terr.printStackTrace();
}
catch(InterruptedException ierr){
System.out.println("Interrupted exception:");
ierr.printStackTrace();
}catch(ExecutionException err){
System.out.println("Exeuction exception:");
err.printStackTrace();
Thread.currentThread().interrupt();
}
}
executor.shutdown();
}
}
class RunnableEx implements Runnable{
public void run() {
// code in here
System.out.println("Thread name:"+Thread.currentThread().getName());
try{
Random r = new Random();
if (r.nextInt(2) == 1){
Thread.sleep(2000);
}else{
Thread.sleep(4000);
}
System.out.println("eee:"+1/0);
}catch(InterruptedException irr){
irr.printStackTrace();
}
}
}
output:
Thread name:pool-1-thread-1
Timeout exception
Thread name:pool-1-thread-1
java.util.concurrent.TimeoutException
at java.util.concurrent.FutureTask.get(FutureTask.java:201)
at ExceptionDemo.main(ExceptionDemo.java:20)
Thread name:pool-1-thread-1
Exeuction exception:
java.util.concurrent.ExecutionException: java.lang.ArithmeticException: / by zero
at java.util.concurrent.FutureTask.report(FutureTask.java:122)
at java.util.concurrent.FutureTask.get(FutureTask.java:202)
at ExceptionDemo.main(ExceptionDemo.java:20)
Caused by: java.lang.ArithmeticException: / by zero
at RunnableEx.run(ExceptionDemo.java:49)
at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:471)
at java.util.concurrent.FutureTask.run(FutureTask.java:262)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1145)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:615)
at java.lang.Thread.run(Thread.java:744)
Interrupted exception:
java.lang.InterruptedException
at java.util.concurrent.FutureTask.awaitDone(FutureTask.java:400)
at java.util.concurrent.FutureTask.get(FutureTask.java:199)
at ExceptionDemo.main(ExceptionDemo.java:20)
Timeout exception
java.util.concurrent.TimeoutException
at java.util.concurrent.FutureTask.get(FutureTask.java:201)
Thread name:pool-1-thread-1
at ExceptionDemo.main(ExceptionDemo.java:20)
Thread name:pool-1-thread-1
Timeout exception
java.util.concurrent.TimeoutException
at java.util.concurrent.FutureTask.get(FutureTask.java:201)
at ExceptionDemo.main(ExceptionDemo.java:20)
TimeoutException : Exception thrown when a blocking operation times out.
In above example, some tasks are taking more time (due to 4 seconds sleep) and blocking operation of get() on Future
Either increase the time-out or optimize Runnable task.
ExecutionException: Exception thrown when attempting to retrieve the result of a task that aborted by throwing an exception => The computation threw an exception
In above example, this Exception is simulated through ArithmeticException: / by zero
Generally, you should catch it fix the root cause if it is trivial as quoted in the example.
InterruptedException: Thrown when a thread is waiting, sleeping, or otherwise occupied, and the thread is interrupted, either before or during the activity.
In above example, this Exception is simulated by interrupting current Thread during ExecutionException.
Generally, you should catch it don't act on it.

Categories

Resources