I have a future that does some intensive task. I call that future with a timeout. If it times out, I throw an exception back to client as well as create another scheduledfuture to cancel first future eventually after a while. The idea is to give sometime after initial timeout for future to complete its task, but if it doesn't complete in that time, just kill it.
My code looks like
try {
return future.get(5, TimeUnit.SECONDS);
} catch (TimeoutException) {
//create a scheduledfuture here which waits for another 5s
// and kill the above future is it is still not done
//the callable of scheduledfuture looks like -
/*
if (!future.isDone()) {
future.cancel(true);
}
*/
}
Now two questions here -
1. The future.cancel(true) will just set the interrupt flag to true. It will not end the task as it is. How should I end the task? Is there a JVM process internally that checks threads for interrupted flag and terminates them if true?
2. As the interrupted flag is now set, after the task completes, is there a process that resets the flag? Else that thread managed through ExecutorService will fail with InterruptedException when it tries to take up next request which contains a blocking call.
How should I end the task?
Run the task is a separate process and kill the process to stop it. There is no safe way to stop a thread in Java, unless the task has been coded to support it.
As the interrupted flag is now set after the task completes, is there a process that resets the flag?
Yes, the ExecutorService resets the interrupted flag.
Related
I am considering an implementation of an ExecutorService to run a series of tasks. I plan to use the internal queue to have a few tasks waiting for their turn to run. Is there some way to interrupt the task (the Runnable) that is currently running in an ExecutorService thread, and keep the thread alive to run the next task? Or is only possible to call .shutdown() and then create a new ExecutorService?
I have found this and wanted to know if there are any other solutions.
Instead of interfering with the threads you may want to have a Task class (that extends or wraps the Runnable) which implements an interrupt mechanism (e.g. a boolean flag).
When you execute your task you need to check this flag periodically and if it is set, the task should stop what it is doing. You might want to return a specific result at this point, that tells your code that the task was cancelled succesfully.
If a user now decides that he no longer requires the results from this task,
you will have to set this flag. However the task might have already completed at this point of time so you still need to deal with the cases where the result already exists but the user does no longer care about it.
An interrupt on a thread level does not guarantee that the thread stops working. This will only work if the thread is in a state where it can receive an interrupt.
Also you should not interfere with the Threads of the ExecutorSerivce directly, as you might unintentionally stop a different task or stop the ExecutorSerivce from working properly.
Why would you want to kill that task and continue with the next one? If it is a question of times you can define that the threads that are taking longer than you declared in the method that executes them are automatically canceled. E.g:
ExecutorService executor = Executors.newSingleThreadExecutor();
executor.invokeAll(Arrays.asList(new Task()), 60, TimeUnit.SECONDS); // Timeout of 60 seconds.
executor.shutdown();
If any of the threads takes longer than 60 seconds it will throw a cancellation.Exception() that you must catch
I have an ExecutorService that runs a few threads.
What I am trying to accomplish is to execute, and then wait for all threads to terminate. To give you more background, every thread1 connects to a website.
This is what I came up with:
public static void terminateExecutor(ExecutorService taskExecutor) {
taskExecutor.shutdown();
try {
taskExecutor.awaitTermination(2, TimeUnit.SECONDS);
} catch (InterruptedException e) {
System.out.println("Some tasks were interrupted!"); //This gets printed
}
}
Now, strangely enough, the main thread that uses the ExecutorService terminates, but the thread1s in it don't.
I noticed this because thread1 threw an error (the main thread at this point was already dead) telling me that it didn't find the URL specified (so I guess it's something related to connections).
Is it possible that awaitTermination doesn't terminate the thread1 because its trying (and retrying it seems) to connect to an invalid link?
I cannot stop the thread1 in any other way (or at least to my knowledge I can't), because there isn't any kind of loop.
EDIT:
I get thread1 by creating a new class and feeding it to the executor.
for (....)
{
String urlToVisit = globalUrl + links.get(i);
Thread thread1 = new MagicalThread(urlToVisit, 2).getThread();
executor.execute(thread1);
}
terminateExecutor(executor.getExecutor());
From the Javadoc (emphasis mine):
Blocks until all tasks have completed execution after a shutdown request
You need to call shutdown() before calling awaitTermination, otherwise it does nothing meaningful.
The executor uses interruption to let the threads know it's time to quit. If your tasks are using blocking I/O then they will be blocked and can't check the interrupt flag. There is no ability for the blocked task to respond to the interruption in the way that happens with sleep or wait, where interruption causes the threads to wake up and throw an InterruptedException.
If you set a timeout on the socket then, once the socket times out, the task can check for interruption. Also you can have the task respond to interrupt by closing the socket. See https://www.javaspecialists.eu/archive/Issue056.html
Be aware that implementing this in a threadpool is more involved than in the example given in the linked article. Nothing about the executor lets the pool call methods on a task besides run. One way to do it would be to put a reference to the socket in a ThreadLocal. Then you could make a ThreadFactory for the pool to use to subclass Thread with a method that overrides the interrupt method on the thread to get the socket from the ThreadLocal and close it.
When
taskExecutor.awaitTermination(2, TimeUnit.SECONDS);
returns, it doesn't guarantee that the ExecutorService has terminated. Look at its return value:
[Returns] true if this executor terminated and false if the timeout elapsed before termination
You don't check this value, but I'll bet it's returning false if the thing you're running in the ExecutorService is still running.
Suppose I have a Runnable instance:
class MyTask implements Runnable {
public void run() {
//some heavy calculation which takes time
Thread.sleep(5000)
//rest code
...
}
}
Then, I use ExecutorService to submit the above task:
ExecutorService service = Executors.newFixedThreadPool(3);
Future<?> task = service.submit(new MyTask());
Now, I can cancel the task by task.cancel(true);. What I have understood is that the task.cancel(true) will interrupt the working thread in which this task is running, like Thread.currentThread().interrupt(). But this only sets a flag to tell that the working thread is interrupted.
My question is: if MyTask Runnable has started running, how actually does future.cancel(true) stops my code in run() continuing executing the rest code? Is there a periodical checking for the working thread's interrupted flag underneath? I mean I don't understand how the code in run() can be canceled by only set the interrupted flag to true.
Future.cancel does not guarantee that your worker code will stop executing. What it does is set the interrupted flag and cause any blocking JDK calls to throw an InterruptedException. Your worker code may choose to rethrow the interrupted exception and periodically check the interrupted flag, in which case the cancel mechanism will work. Otherwise you may choose to swallow InterruptedException and disregard the iterrupted flag, in which case the cancel mechanism will do nothing but set the cancelled flag to true.
See http://www.ibm.com/developerworks/library/j-jtp05236/
There is a method called isInterrupted(), this tells the running code in the thread that it is interrupted by returning a true/false.
This is usually checked by the methods like wait, sleep which you might invoke in the thread.
If however you do not use these methods, then you will have to manually check this method [ isInterrupted() ] to determine whether someone has interrupted your thread.
If by any chance you get a true, you can decide what action to perform (let us say for example: throw a InterruptedException or break from a loop, etc...)
I'm having this odd behaviour. My program hangs eventhough I'm setting a time to force terminate it. could anyone point out what this strange behaviour could be?
here is my code where I start the threads
protected void pendingTaskStarter() throws Exception {
ExecutorService service = Executors.newFixedThreadPool(maxThreadNum);
ArrayList<Future<Runnable>> futures = new ArrayList<Future<Runnable>>();
System.out.println("max thread num: " + maxThreadNum);
for(int i=0;i<maxThreadNum;i++){
Thread t = new PendingTaskConsumer();
Future<?> f=service.submit(t);
futures.add((Future<Runnable>) f);
}
for (Future<?> future:futures) {
future.get(5l,TimeUnit.MINUTES); // maximum thread's life is 5min (5l <-- 5 in long )
}
service.shutdownNow();
}
I am 100% sure that my program hangs somewhere in PendingTaskConsumer class based on the outputs within PendingTaskConsumer class.
Anyways codes in PendingTaskConsumer should be irrelevant as thread is supposedly forced to be terminated.
My question is in what scenraios the following line does not do as its expected.
future.get(5l,TimeUnit.MINUTES);
The program is running on Linux(Ubuntu) and using openjdk-7-jdk backage ( version 1.7)
As #GPI already stated in his/her answer, cancellation won't work properly, if your tasks do not repond to thread interruption via Thread.interrupt(). See Oracle: The Java™ Tutorials - Concurrency - Interrupts or Java Executors: how can I stop submitted tasks?.
But even if your tasks do not immediately stop if the thread is interrupted (=the interruption flag is set), you can timeout your method. Just don't listen to task completion by invoking every single get() method of your Futures! That's not necessary as you are not really interested in their result. Just shutdown your ExecutorService and wait for its termination.
protected void pendingTaskStarter() throws InterruptedException {
ExecutorService service = Executors.newFixedThreadPool(maxThreadNum);
for (int i = 0; i < maxThreadNum; i++) {
service.submit(new PendingTaskConsumer());
}
// Shutdown service.
// This will continue to process already submitted tasks.
service.shutdown();
try {
// wait at least 5 minutes for the tasks to complete
if (!service.awaitTermination(5, TimeUnit.MINUTES)) {
// still not done yet -> force shutdown
// this will interrupt currently running tasks.
service.shutdownNow();
}
} catch (InterruptedException ex) {
// someone interrupted this thread. Shutdown tasks immediately
service.shutdownNow();
// propagate exception
throw ex;
}
}
So what happens here?
First, all tasks are submitted.
Then shutdown() is called on the ExecutorService. Note that the service will continue to execute already submitted tasks, but it will not accept new tasks.
Now, we wait for the service to terminate by calling awaitTermination with a timeout of 5 minutes. If this method returns true, which means, that the service has terminated within time, everything is fine and we're done. But if it returns false after 5 minutes, it means that the service is still running because there are some tasks that need more time to complete.
In that case, we shutdown the service immediately by calling shutdownNow(). Note that this method will not block! It just attempts to cancel all running tasks, usually by interrupting the threads that are currently executing them. This is exactly why your tasks should response to thread interruption properly! If they don't do this, interrupting the thread will have no effect at all!
No matter if shutdownNow was successful - we are done and do not wait any longer. So there might still be some tasks that are running because they don't react upon thread interruption (usually because a task is either not implemented properly or it is uninterruptibly on purpose). But we simply don't care.
Note the exception handler: When another thread interrupts the thread that is calling our method while it is waiting in method awaitTermination, an InterruptedException is thrown. We handle it by shutting down the service and re-throwing the exception! That is a good thing and makes our method a long-running-operation that is cancellable by itself!
Well... proper exception handling seems to be missing.
/**
* Waits if necessary for at most the given time for the computation
* to complete, and then retrieves its result, if available.
*
* #param timeout the maximum time to wait
* #param unit the time unit of the timeout argument
* #return the computed result
* #throws CancellationException if the computation was cancelled
* #throws ExecutionException if the computation threw an
* exception
* #throws InterruptedException if the current thread was interrupted
* while waiting
* #throws **TimeoutException if the wait timed out**
*/
V get(long timeout, TimeUnit unit)
throws InterruptedException, ExecutionException, TimeoutException;
If your call to future.get(5l,TimeUnit.MINUTES); expires, then an Exception is thrown and your service is never shut down.
So (one can assume) its internal threads are still running, at least the one that is executing your long running task). Seeing those are non-daemons thread (you'd have to custom the ThreadFactory of your executor for them to be), those pending threads prevent the JVM from shutting down.
If you wish to terminate the tasks forcibly, you can :
design your runnable task to respond to Thread.isInterrupted(), and exit when it sees that become true. (The practical effect of shutdownNow is to set the interrupted flag of your executor's thread )
If you can't (because your are blocked in some library's method that does not listen to interruption), then having a dameon thread seems like the only option.
But anyway, I'd put the executor's shutdown either earlier, or in a finally clause.
I have a Runnable that runs from an Executor.
The runnable is blocked waiting in an SychronousQueue.take. How can I make sure the take will be interrupted when I do executor.shutdown?
+1 to #Eugene. ExecutorService.shutdown() shuts the thread-pool down but any submitted jobs will continue to run until they finish. If you use shutdownNow() instead, it will actually interrupt the threads. This doesn't mean that they will stop immediately but it does mean that if they are blocked in queue.take() or their next call to queue.take() it will throw an InterruptedException so the thread can exit.
To quote from the Javadocs:
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 any task that fails to respond to interrupts may never terminate.
When your threads are calling queue.take() they should have something like the following code:
try {
work = queue.take();
...
} catch (InterruptedException e) {
// re-interrupt the thread which is always a good pattern
Thread.currentThread().interrupt();
// quit the processing thread
return;
}
You can do something like this may be?
executor.shutdown();
if (!executor.awaitTermination(SHUTDOWN_TIME)) {
executor.shutdownNow();
}
As specified in the javadoc of take it will throw an InterruptedException when the thread waiting is interrupted. So you need to make sure that your executor implementation will call Thread.interrupt() on all it's owning threads on shutdown.