How to interrupt the future, but still wait for its completion?

I have a series of jobs that I have queued using ExecutorService. If the user clicks cancel, I need to notify those tasks that they should stop as soon as possible. However, sometimes they are in critical sections of code that must be executed before the parent thread must continue. How can i do this? I do not want to use my own cancellation flag, because it will not cause sleep / wait for the exit.

I thought this code would work, but it does not do what I want:

while( true ) { //Do this in a loop. If our thread is interrupted, we call cancel on the threads (to try to get them to hurry up by skipping non-essential stuff), but we still need to wait for them to finish. try { for( Future<Void> future : futures ) { future.get(); //I thought that this would continue waiting, even if I call cancel, but it doesn't. How can I wait for the future to finish? } break; //OK, everything is finished, exit the wait loop. } catch( InterruptedException e ) { wasInterrupted = true; //We'll rethrow the exception laster as an AbortException. //Need to wait for futures to finish, even if it canceled. log.info( "Attempting to interrupt threads that are reading changes..." ); for( Future<Void> future : futures ) { future.cancel( true ); //I want to tell the threads to 'hurry up' and skip non-essential stuff. } } catch( ExecutionException e ) { throw e.getCause(); } } //I shouldn't get to this line until all futures have finished! 
+6
source share
2 answers

How to interrupt the future, but still wait for its completion?

An interesting problem. Your code will not work, because when you cancel Future , as you discovered, you cannot call get() again on it, because it will raise a CancellationException .

If I understand your requirements:

  • You should be able to interrupt threads because you want to stop sleep , wait , etc.
  • You still want to receive the results of the tasks after they are canceled.

In this case, you should not use Future . Instead, use your own work shells and wait for the ExecutorService finish with executorService.awaitTermination(...) .

If you need the result of your tasks, then your Runnable class will contain the result of the calculation and will have the boolean done flag. The waiting thread will expect that for each Runnable its done flag will be set to true. When the shell completes its run() method, it will set done and notify() to itself. This needs to be done in the finally block.

If the waiting thread is interrupted, it will call executorService.shutdownNow(true) to interrupt all threads, but will continue the loop, waiting for completion.

Something like that.

+4
source

"as soon as possible" means that the thread must know when to exit

In either case, you can use the interrupt flow policy.

  if (Thread.interrupted()) // Clears interrupted status! throw new InterruptedException(); 

see also

http://www.ibm.com/developerworks/java/library/j-jtp05236/index.html?ca=drs-

0
source

All Articles