Future.cancel() followed by Future.get() kills my thread - java

I want to use the Executor interface (using Callable) in order to start a Thread (let's call it callable Thread) which will do work that uses blocking methods.
That means the callable Thread can throw an InterruptedException when the main Thread calls the Future.cancel(true) (which calls a Thread.interrupt()).
I also want my callable Thread to properly terminate when interrupted USING other blocking methods in a cancellation part of code.
While implementing this, I experienced the following behavior: When I call Future.cancel(true) method, the callable Thread is correctly notified of the interruption BUT if the main Thread immediately waits for its termination using Future.get(), the callable Thread is kind of killed when calling any blocking method.
The following JUnit 5 snippet illustrates the problem.
We can easily reproduce it if the main Thread does not sleep between the cancel() and the get() calls.
If we sleep a while but not enough, we can see the callable Thread doing half of its cancellation work.
If we sleep enough, the callable Thread properly completes its cancellation work.
Note 1: I checked the interrupted status of the callable Thread: it is correctly set once and only once, as expected.
Note 2: When debugging step by step my callable Thread after interruption (when passing into the cancellation code), I "loose" it after several step when entering a blocking method (no InterruptedException seems to be thrown).
#Test
public void testCallable() {
ExecutorService executorService = Executors.newSingleThreadExecutor();
System.out.println("Main thread: Submitting callable...");
final Future<Void> future = executorService.submit(() -> {
boolean interrupted = Thread.interrupted();
while (!interrupted) {
System.out.println("Callable thread: working...");
try {
Thread.sleep(500);
} catch (InterruptedException e) {
System.out.println("Callable thread: Interrupted while sleeping, starting cancellation...");
Thread.currentThread().interrupt();
}
interrupted = Thread.interrupted();
}
final int steps = 5;
for (int i=0; i<steps; ++i) {
System.out.println(String.format("Callable thread: Cancelling (step %d/%d)...", i+1, steps));
try {
Thread.sleep(200);
} catch (InterruptedException e) {
Assertions.fail("Callable thread: Should not be interrupted!");
}
}
return null;
});
final int mainThreadSleepBeforeCancelMs = 2000;
System.out.println(String.format("Main thread: Callable submitted, sleeping %d ms...", mainThreadSleepBeforeCancelMs));
try {
Thread.sleep(mainThreadSleepBeforeCancelMs);
} catch (InterruptedException e) {
Assertions.fail("Main thread: interrupted while sleeping.");
}
System.out.println("Main thread: Cancelling callable...");
future.cancel(true);
System.out.println("Main thread: Cancelable just cancelled.");
// Waiting "manually" helps to test error cases:
// - Setting to 0 (no wait) will prevent the callable thread to correctly terminate;
// - Setting to 500 will prevent the callable thread to correctly terminate (but some cancel process is done);
// - Setting to 1500 will let the callable thread to correctly terminate.
final int mainThreadSleepBeforeGetMs = 0;
try {
Thread.sleep(mainThreadSleepBeforeGetMs);
} catch (InterruptedException e) {
Assertions.fail("Main thread: interrupted while sleeping.");
}
System.out.println("Main thread: calling future.get()...");
try {
future.get();
} catch (InterruptedException e) {
System.out.println("Main thread: Future.get() interrupted: Error.");
} catch (ExecutionException e) {
System.out.println("Main thread: Future.get() threw an ExecutionException: Error.");
} catch (CancellationException e) {
System.out.println("Main thread: Future.get() threw an CancellationException: OK.");
}
executorService.shutdown();
}

When you call get() on a canceled Future, you will get a CancellationException, hence will not wait for the Callable’s code to perform its cleanup. Then, you are just returning and the observed behavior of threads being killed seems to be part of JUnit’s cleanup when it has determined that the test has completed.
In order to wait for the full cleanup, change the last line from
executorService.shutdown();
to
executorService.shutdown();
executorService.awaitTermination(1, TimeUnit.DAYS);
Note that it is simpler to declare unexpected exceptions in the method’s throws clause rather than cluttering your test code with catch clauses calling Assertions.fail. JUnit will report such exceptions as failure anyway.
Then, you can remove the entire sleep code.
It might be worth putting the ExecutorService management into #Before/#After or even #BeforeClass/#AfterClass methods, to keep the testing methods free of that, to focus on the actual tests.¹
¹ These were the JUnit 4 names. IIRC, the JUnit 5 names are like #BeforeEach/#AfterEach resp. #BeforeAll/#AfterAll

Related

ExecutorService.awaitTermination runs into timeout despite active tasks

I have the following implementation:
final ExecutorService service = Executors.newFixedThreadPool(4);
final List<Callable> taskList = new LinkedList<>();
for (Path path : paths) {
final SomeCallable task = new SomeCallable(path);
taskList.add(task);
service.submit(task);
}
synchronized (this) {
try {
this.wait();
shutdown(service);
} catch (InterruptedException e) {
shutdown(service);
}
}
And the following shutdown(service) method:
protected void shutdown(final ExecutorService service) {
List<Runnable> abortedCallables = service.shutdownNow();
try {
if (!service.awaitTermination(2, TimeUnit.MINUTES)) {
System.out.println("timeout");
}
}
catch (InterruptedException e) {
// (Re-)cancel all Callables if current thread has been interrupted
service.shutdownNow();
// Preserve interrupt status
Thread.currentThread().interrupt();
}
}
My problem is the following: paths is a list of a lot of Path instances. All of these paths will undergo some processing within a SomeCallable instance. Usually, this thread waits until all paths have been successfully handled within their SomeCallable. Once all paths have been processed shutdown(service) will be called.
However, it may happen that this thread is interrupted and has to be shutdown immediately. Therefore, I call shutdown(service) within the catch-block. What is working is, that currently running SomeCallable-instances will be finished and none of the tasks within the ExecutorService's thread pool will be started. Nonetheless, awaitTermination always runs into the 2 minute timeout. Why is this?
I assumed that awaitTermination waits for currently active running tasks to terminate (hence, wait for a maximum of 4 tasks -> thread pool size). Two minutes - in my case - is more than enough time for the 4 tasks to finish. As by calling shutdownNow() no new tasks from the queue should be started I wonder why I still get the timeout.
Any ideas?

What happens to remaining thread of invokeAny Executor Service

InWhen invokeAny successfully returns, what happens to remaining threads? Does it get killed automatically? If not how can I make sure that thread is stopped and return back to threadpool
ExecutorService executorService = Executors.newFixedThreadPool(10);
executorService.invokeAny(callables);
Just elaborating more on the topic.
What happens to remaining threads
If the treads are executing methods which throw InterruptedException then they receive the exception. Otherwise they get their interrupted flag set to true.
Does it get killed automaticlly?
Not really.- If they are running in infinite loop then you need to make sure you do not swallow InterruptedException and exit the thread in the catch block.- If you are not expecting the exception then you need to keep checking flag using Thread.interrupted() or Thread.currentThread().isInterrupted() and exit when it's true.
- If you are not running infinite loop then the threads will complete their tasks and stop. But their results will not be considered.
In following code both task, and task2 keep running even the service is stopped and main method exits:
public class Test {
public static void main(String[] args) throws Exception {
Callable<String> task1 = () -> {
for (;;) {
try {
Thread.sleep(9000);
System.out.println(Thread.currentThread().getName()+
" is still running..");
} catch (InterruptedException e) {
System.out.println(Thread.currentThread().getName()
+ " has swallowed the exception.");
//it is a good practice to break the loop here or return
}
}
};
Callable<String> task2 = () -> {
for(;;) {
if(Thread.interrupted()) {
//it is a good practice to break the loop here or return
System.out.println(Thread.currentThread().getName()+
" is interrupted but it is still running..");
}
}
};
List<Callable<String>> tasks = List.of(task1, task2, () -> "small task done!");
ExecutorService service = Executors.newFixedThreadPool(4);
String result = service.invokeAny(tasks);
System.out.println(result);
service.shutdownNow();
System.out.println("main thread done");
}
}
Output:
small task done!
pool-1-thread-2 is interrupted but it is still running..
pool-1-thread-1 has swallowed the exception.
pool-1-thread-1 has swallowed the exception.
main thread done
pool-1-thread-1 is still running..
pool-1-thread-1 is still running..
Upon calling the method invokeAny they are all cancelled/stop when the remaining threads are not yet completed.
Here is the documentation of it:
Upon normal or exceptional return, tasks that have not completed are cancelled.

Java main process suspended because of exceptions thrown from threads

The main process:
int cpus = Runtime.getRuntime().availableProcessors();
ExecutorService executor = Executors.newFixedThreadPool(cpus);
List<Callable<Object>> todo = new ArrayList<Callable<Object>>(lines.size());
for (int r = 0; r < lines.size(); r++) {
String filename = r + 1 + "";
todo.add(Executors.callable(new AppConsole(filename, lines.get(r))));
}
List<Future<Object>> answers = executor.invokeAll(todo);
The AppConsole class implements Runnable and the overriden run method is as follows:
public void run() {
try{
} catch (SecurityException exception) {
exception.printStackTrace();
} catch (FileNotFoundException exception) {
exception.printStackTrace();
} catch (IOException exception) {
exception.printStackTrace();
} catch (SAXException exception) {
exception.printStackTrace();
} catch (Exception exception) {
exception.printStackTrace();
} finally {
if (output != null) {
output.close();
}
}
}
}
The main process is suspended and cannot finish because of a connection timeout exception thrown from one of the threads. Now I can see the cpu usage drops to 0% and the memory consumption keeps at the same level when it got suspended.
Could someone please help me solve this problem? At least, help me make the main process finish?
Throwing an exception frees up the tasks and the main thread. The ExecutorService treats an Exception throw much like another return value and doesn't have a problem handling it.
The main thread will only block waiting for one of your tasks to complete. I would look at the tasks/threads which are still active to see what they are doing e.g. perhaps they haven't timed out yet.
you could use the alternative version of invokeAll that takes an explicit timeout value :
http://docs.oracle.com/javase/6/docs/api/java/util/concurrent/ExecutorService.html
invokeAll(Collection<? extends Callable<T>> tasks,
long timeout,
TimeUnit unit)
this way you can force all of your tasks to timeout after, say, 30 seconds. Then you can inspect the Futures returned to see which have completed.
You just need to add:
executor.shutdown();
This waits when all tasks will be completed and shutdown all threads, application will exit after that.
Please see javadoc for newFixedThreadPool:
Creates a thread pool that reuses a fixed number of threads operating
off a shared unbounded queue. At any point, at most nThreads threads
will be active processing tasks. If additional tasks are submitted
when all threads are active, they will wait in the queue until a
thread is available. If any thread terminates due to a failure during
execution prior to shutdown, a new one will take its place if needed
to execute subsequent tasks. The threads in the pool will exist until
it is explicitly shutdown.

Time limit on the execution of a Java function

I am trying to construct two threads, thread A is the main thread and thread B is the second thread, thread B is updating a variable through a time consuming function (this variable should be shared between both threads, because eventually thread A needs to use that variable as well), but I want thread A to terminate thread B if thread B takes too long to complete (using an exception).
What I tried is the following:
Thread thread = new Thread() {
public void run() {
/// run something that could take a long time
}
};
synchronized (thread) {
thread.start();
}
System.err.println("Waiting for thread and terminating it if it did not stop.");
try {
thread.wait(10000);
} catch (InterruptedException e) {
System.err.println("interrupted.");
}
Should that give the expected behavior of terminating a behavior in case it has run more than 10 seconds? The thread object gets deleted after the wait, because the method that runs the thread returns.
Right now, what happens with this code is that I always get java.lang.IllegalMonitorStateException on the wait(10000) command.
You will always get a IllegalMonitorStateException if you are calling wait() on an object that you are not synchronized on.
try {
// you need this to do the wait
synchronized (thread) {
thread.wait(10000);
}
} catch (InterruptedException e) {
System.err.println("interrupted.");
}
If you are waiting for the thread to finish then you probably are trying to do a:
try {
thread.join(10000);
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
System.err.println("interrupted.");
}
Unfortunately, you do not know at that point if the thread is running because join doesn't return whether or not it timed out (grumble). So you need to test if the thread.isAlive() after the join.
If you are asking how you can cancel the thread if it runs for longer than 10000 millis, then the right thing to do is use thread.interrupt(). This will cause any sleep() or wait() methods to throw an InterruptedException and it will set the interrupt flag on the thread.
To use the interrupt flag your thread should be doing something like:
while (!Thread.currentThread.isInterrupted()) {
// do it's thread stuff
}
Also, it is always a good pattern to do something like the following because once the InterruptedException is thrown, the interrupt flag has been cleared:
} catch (InterruptedException e) {
// set the interrupt flag again because InterruptedException clears it
Thread.currentThread.interrupt();
System.err.println("interrupted.");
}
That code is incorrect. Method wait is declared in Object class and is intended to suspend current thread using as monitor instance of the object on which it is called. You may invoke this method only in synchronized section, that is why you get your exception.
Regarding to your problem: in general you can not stop another thread if it does not want to stop. So you should invoke Thread.interrupt to notify the thread that it should stop working and it is up to that thread to decide to take into account that notification or not. To check if thread is interrupted you may use interrupted() or isInterrupted() methods.

Java: Force stopping of ExecutorService threads

My code:
String[] torrentFiles = new File("/root/torrents/").list();
if(torrentFiles.length == 0 || torrentFiles == null)
{
System.exit(0);
}
ex = Executors.newFixedThreadPool(3);
for(String torrentFile : torrentFiles)
{
ex.submit(new DownloadTorrent("/root/torrents/" + torrentFile));
}
ex.shutdown();
try
{
ex.awaitTermination(30, TimeUnit.MINUTES);
}
catch(InterruptedException ex1)
{
Logger.getLogger(Main.class.getName()).log(Level.SEVERE, null, ex1);
}
But sometimes torrent downloading takes unknown time value and «awaitTermination» not works as I want. I need to stop all executed threads instantly after half an hour but as I know «awaitTermination» just only use interrupt() method which works only in loops or waiting. So timeout not works if this moment happens. So, how to?
Instant thread termination is never guaranteed, unless the thread checks periodically for isInterrupted() flag (or is waiting in interruptable method, i.e. which throws InterruptedException).
Consider implementing your worker threads in manner, when they check periodically for isInterrupted(). This may be something like that:
public void run() {
byte[] data;
do {
data = receiveDataChunk(timeout);
processData(data);
} while(!isInterrupted() && data != null);
}
ExecutorService.shutdownNow() will try to stop all the executing threads..
Here is a quote from javadoc
List<Runnable> shutdownNow()
Attempts to stop all actively
executing tasks, halts the processing
of waiting tasks, and returns a list
of the tasks that were awaiting
execution.
There are no guarantees
beyond best-effort attempts to stop
processing actively executing tasks.
For example, typical implementations
will cancel via Thread.interrupt(), so
if any tasks mask or fail to respond
to interrupts, they may never
terminate.
Since downloading a torrent probably involves blocking IO operations, simply calling cancel()/shutdownNow() won't be enough, because blocking IO operations are not guaranteed to terminate when their respective threads are interrupted.
You also need to close the underlying sockets in order to cancel blocking IO, see How to terminate a thread blocking on socket IO operation instantly?.
ExecutorService.submit(...) returns a Future<?> that has a cancel() method. You should keep track of these can call it when you want each task to stop.
Am Using this code i have created.
Its generating many pdf files from many html templates using wkhtmltopdf .
so i want to increase performance of creating handreds without keep client waiting, this is only one part of implementation.
About getListOfCallables its returning the correct optimal
threshold for # of threads to use in fixed pool creation.
So i cant handle having lots of un dead threads laying around it made my EC2
CPU 100% stuck.
I used :
shutdown()
shutdownNow() in else of await
shutdownNow() in exception part
List fileGenerationHtmlToPdfList = getListOfCallables(paths, name, options);
ExecutorService executorService = Executors.newFixedThreadPool(fileGenerationHtmlToPdfList.size());
List<Future<ArrayList<File>>> futures = null;
try {
futures = executorService.invokeAll(fileGenerationHtmlToPdfList);
try {
for(Future f: futures) {
files.addAll((ArrayList<File>)f.get());
}
} catch (InterruptedException ex) {
Logger.getLogger(FileUtil.class.getName()).log(Level.SEVERE, "Interrupted Exception " , ex);
} catch (ExecutionException ex) {
Logger.getLogger(FileUtil.class.getName()).log(Level.SEVERE, "Interrupted Exception " , ex);
}
} catch (InterruptedException ex) {
Logger.getLogger(FileUtil.class.getName()).log(Level.SEVERE, "Interrupted Exception " , ex);
}
executorService.shutdown();//try shutdown
try {
if (executorService.awaitTermination(5, TimeUnit.SECONDS)) {
Logger.getLogger(FileUtil.class.getName()).log(Level.SEVERE, "Done ShutDowned");
} else {
executorService.shutdownNow();
}
} catch (InterruptedException ex) {
executorService.shutdownNow();
Logger.getLogger(FileUtil.class.getName()).log(Level.SEVERE, "Interrupted Exception " , ex);
}
Now I have to stop threads from a pool. I am doing it such a way. It may be not a good idea. Comment, please, if so.
boolean isTerminated = mPoolThreads.isTerminated();
while (!isTerminated) {
mPoolThreads.shutdownNow();
isTerminated = mPoolThreads.isTerminated();
Log.i(Constants.LOG_TAG, "Stop threads: the threads are not terminated yet");
}
Log.w(Constants.LOG_TAG, "Stop threads: Terminated");

Categories

Resources