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.
Related
I want to wrap a Runnable in CompletableFuture to be computed asynchronously, but with control over when does the computation begin and end. I've created a CompletableFuture with CountDownLatch to block the processing, but the following snippet throws an error:
CountDownLatch countDownLatch = new CountDownLatch(1);
CompletableFuture completableFuture = CompletableFuture.runAsync(() -> {
try {
countDownLatch.await();
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("Stop");
});
Thread.sleep(1000L);
System.out.println("Start");
completableFuture.get(1000L, TimeUnit.MILLISECONDS);
countDownLatch.countDown();
Start
Exception in thread "main" java.util.concurrent.TimeoutException
at java.util.concurrent.CompletableFuture.timedGet(CompletableFuture.java:1771)
at java.util.concurrent.CompletableFuture.get(CompletableFuture.java:1915)
at Sandbox.main(Sandbox.java:23)
When I call get without timeout on the other hand, it freezes (only Start is printed).
I expect the runnable in CompletableFuture to run when countDownLatch.countDown(); is called.
You are waiting till the timeout expires without allowing the thread to proceed. The Future.get is blocking and that will never allow you to countDown the Latch before the timeout expires ever, hence your thread never completes. What you have to do here is, first, let the thread proceed by calling the countDown on the Latch and then wait with a timeout in the get call. Just inverting the two lines would solve the issue. Here's how it looks.
countDownLatch.countDown();
completableFuture.get(1000L, TimeUnit.MILLISECONDS);
In fact, if you remove the timeout from the get call (it blocks indefinitely), then this is a typical example of a Deadlock in a system. The worker thread waits until the main thread counts down the latch, while main thread waits for the worker thread to complete so that it can go ahead and countDown the latch. Fortunately, the time out passed to get enables Probabilistic deadlock avoidance. On the contrary, you can cancel the future at any time and avoid potential deadlocks as far as your tasks are responsive to the interruption.
Because of CompletableFuture#get is a blocking call. So, countDownLatch.countDown(); will not execute till the time CompletableFuture#get get the result. CompletableFuture will not complete and return the result as it will wait to countDownLatch to count down. So, basically you have created a dependency between 2 thread such that one will wait for another and vice-versa.
From multiple articles around the internet it's advised not to swallow InterruptedException. It makes much more sense to do it with thread pool executors something like this when I'm going to reuse the same thread.
public static void main(String[] args) throws InterruptedException {
ExecutorService executor = Executors.newSingleThreadExecutor();
Future<?> future = executor.submit(() -> {
printNumbers(); // first call
printNumbers(); // second call
});
Thread.sleep(3_000);
executor.shutdownNow(); // will interrupt the task
executor.awaitTermination(3, TimeUnit.SECONDS);
}
private static void printNumbers() {
for (int i = 0; i < 10; i++) {
System.out.print(i);
try {
Thread.sleep(1_000);
} catch (InterruptedException e) {
Thread.currentThread().interrupt(); // preserve interruption status
break;
}
}
}
Code sample above from DZone.
But in the case of creating new thread each time like:
Object LOCK = new Object();
public void doSomeJob() {
myThread = new Thread(new Runnable() {
public void run() {
try {
synchronized(LOCK) {
System.out.println("Inside run");
LOCK.wait();
}
} catch(InterruptedException ignored){}
}
}
}
Do I still need to call Thread.currentThread().interrupt();? Will that make any sense?
Good references:
https://codepumpkin.com/interrupt-interrupted-isinterrupted-java-multithreading/
http://michaelscharf.blogspot.com/2006/09/dont-swallow-interruptedexception-call.html
I will give an answer based on section 7.1.2 of great book Concurrency in Practice by Brian Goetz.
In your first example you use ExecutorService. ExecutorService manages it's own threads. You are not the owner of those Threads so you do not know what interruption means to them ( for example ThreadPool might choose to kill Threads that were interrupted and create new ones). That is why you should preserve interruption status when you submit a cancelable task to this pool. This citation applies to this case:
Tasks do not execute in threads they own.They borrow threads owned by a service such as a thread pool. Code that
doesn't own the thread (for a thread pool, any code outside of the thread pool implementation) should be careful to
preserve the interrupted status so that the owning code can eventually act on it, even if the "guest" code acts on the
interruption as well. (If you are housesitting for someone, you don't throw out the mail that comes while they're away - you save it and let them deal with it when they get back, even if you do read their magazines.)
In the second case you manage an instance of Thread manually. So you are the owner of it. Therfore you decide what interruption means to this Thread and you do not have to preserve the Interruption Status in the second case if you do not want to apply any Thread Interruption Policy for it :
What you should not do is swallow the InterruptedException by catching it and doing nothing in the catch block, unless your code is actually implementing the interruption policy for a thread
Note also that Thread Interruption Policy is different than Task Cancellation Policy :
Thread Interruption Policy - defines how Thread reacts to interruption (for example ThreadPool might kill Thread that was interrupted and create a new one). It is defined by the owner of the thread.
Task Cancellation Policy - defines how task reacts to cancellation. Cancellation is usually implemented with interruption. The one who implements the task chooses if task in responsive to interruption. This is easily achieved if your task calls methods that throw InterruptedException. Or you can check the interruption flag of the Thread by calling Thread::isInterrupted (for example in a loop). The implementor of the task chooses how to handle this.
Also you should not take any assumptions of Thread Interruption Policy (if you are not the owner of the Thread). That is why preserving Interruption Status or rethrowing InterruptedException is considered a good practice.
If your lock comes from java.util.concurrent.locks.Lock and is interruptible (using .lockInterruptibly()), it does make sense to interrupt the process so everything might be interrupted and cancelled.
Read chapter Implementation Considerations from the documentation.
But if your lock is non-interruptible (using .lock()) it will not make sense as you won't be able to interrupt the lock.
In your case, you're using wait() which is interruptable as written here, and will throw an InterruptedException.
The explanations in DZone link https://dzone.com/articles/understanding-thread-interruption-in-java in your question are very detailed. Thread.currentThread().interrupt(); raises back interrupted exception status which is cleared before by blocking methods (sleep). It is done to ensure second loop interrupted too (it will catch the exception as it is on the same thread).
Before I finish, I wanted to emphasize on an important detail about
what happens to a thread’s interruption status when a blocking code
responds to interruption by throwing InterruptedException. I had left
out the detail till now to avoid confusion.
Before a blocking code throws an InterruptedException, it marks the
interruption status as false. Thus, when handling of the
InterruptedException is done, you should also preserve the
interruption status by callingThread.currentThread().interrupt().
Let’s see how this information applies to the example below. In the
task that is submitted to the ExecutorService, the printNumbers()
method is called twice. When the task is interrupted by a call
toshutdownNow(), the first call to the method finishes early and then
the execution reaches the second call. The interruption is called by
the main thread only once. The interruption is communicated to the
second execution of the printNumber() method by the call to
Thread.currentThread().interrupt() during the first execution. Hence
the second execution also finishes early just after printing the first
number. Not preserving the interruption status would have caused the
second execution of the method to run fully for 9 seconds.
Where to use Thread.currentThread().interrupt(); depends on your code, second example is not complete to understand the need for it.
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.
I have used shutDown() and shutDownNow(), but both method does not stop all threads immediately. shutDownNow() is more preferable among these two but it waits for the running thread to complete it's task. In my scenario I have a huge task dealing with postgres database and I want to shut down that thread immediately without waiting for the completion of execution.
What is the way to shut down the all the threads immediately?
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.
This method does not wait for actively executing tasks to terminate. Use awaitTermination to do that.
shutdown :
Initiates an orderly shutdown in which previously submitted tasks are executed, but no new tasks will be accepted. Invocation has no additional effect if already shut down.
This method does not wait for previously submitted tasks to complete execution. Use awaitTermination to do that.
http://docs.oracle.com/javase/8/docs/api/java/util/concurrent/ExecutorService.html#shutdown%28%29
or you can see this :
You can use an ExecutorService instead which combines a thread pool with a queue of tasks.
ExecutorService service = Executors.newCachedThreadPool();
// or
ExecutorService service = Executors.newFixedThreadPool(THREADS);
// submit as many tasks as you want.
// tasks must honour interrupts to be stopped externally.
Future future = service.submit(new MyRunnable());
// to cancel an individual task
future.cancel(true);
// when finished shutdown
service.shutdown();
The single "clean" way to stop the threads is, if you have some loops inside, to stop the loop through some boolean variable like "stopThread", and you have to handle the variable.
Example:
public void run(){
for(int i=0; i<1000000 && (!stopThread) ; i++){
// do something
}
}
I doubt that it's possible in safe way.
The safe way to shutdown the executor service as per oracle documentation
void shutdownAndAwaitTermination(ExecutorService pool) {
pool.shutdown(); // Disable new tasks from being submitted
try {
// Wait a while for existing tasks to terminate
if (!pool.awaitTermination(60, TimeUnit.SECONDS)) {
pool.shutdownNow(); // Cancel currently executing tasks
// Wait a while for tasks to respond to being cancelled
if (!pool.awaitTermination(60, TimeUnit.SECONDS))
System.err.println("Pool did not terminate");
}
} catch (InterruptedException ie) {
// (Re-)Cancel if current thread also interrupted
pool.shutdownNow();
// Preserve interrupt status
Thread.currentThread().interrupt();
}
}
If you really want to follow a crude way, I will suggest a solution which may not be 100% accurate and I don't recommend personally. I would like to use ExecutorService methods instead of this crude solution.
Create your own thread and thread pool as per this article
Add one more boolean in Worker thread - boolean runNow = true;
run method of Worker thread will be like this : while ( runNow) { // your logic }
When you want to shut down all the threads, add one more method in ThreadPoolManager. Iterate through myQueue and interrupt all Runnables. Catch that interrupted exception and make the boolean runNow as false.
Depending on how you call the database, you could try to explicitly cancel the query. Se related question.
I am using an ExecutorService for a connection task as below:
ExecutorService executor = Executors.newSingleThreadExecutor();
Future<ApplicationConnection> future = (Future<ApplicationConnection>) executor.submit(new ConnectThread(crf, connoptions));
connection = future.get(300000, TimeUnit.SECONDS);
executor.shutdownNow();
The call() method calls a .connect() method (proprietary API). This connect method spawns various threadpools etc. My concern is that if the future times out and kills the executor, will the threads that may have already spawned by calling the .connect() method in the future also end? I know that killing a thread will also kill any child threads but does this follow the same logic?
You are right in your assumption, if the Future times out, some hanging threads will remain. Even worse, shutdownNow() will not even shutdown your pool thread (not to mention proprietary API threads). It merely stops accepting new jobs. ExecutorService thread pool will terminate all threads once all running tasks finish.
What you can do is to try canceling the future and interrupting it. First handle InterruptedException inside your future:
class ConnectThread implements Callbale<ApplicationConnection> {
public ApplicationConnection call() {
try {
return prioprietaryApi.connect();
} catch(InterruptedException e) {
prioprietaryApi.cleanUp();
throw e;
}
}
}
Now simply run:
future.cancel(true);
However your proprietary API might not handle InterruptedException (it will not rethrow it from connect(), moreover you might not have access to any cleanUp() method.
In these circumstances just... forget about it. That Future will eventually terminate and clean up after itself, ignoring the fact that you no longer wait for it. Of course this might lead to various scalability issues.
BTW if the only thing you want to achieve is limiting the maximum time given method runs, consider TimeLimiter from guava.
As per javadoc
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.