I have to wait for completion of all the threads in an executorService.
Should I use
while(!executor.isTerminated()){...} or
executor.awaitTermination(...)?
What are the pros and cons of these ways?
With executor.isTerminated() your current thread will keep running.
with executor.awaitTermination() the current thread will be blocked.
So it depends on what you want to do in your current thread.
Do you want to do some tasks and periodically check for whether the executor is done, then use executor.isTerminated()?
Or Is the current thread just waiting for the executor to finish. If yes, executor.awaitTermination() makes much more sense.
Do note that an Executor will only be terminated if the shutdown() or shutdownNow() is called.
Recommended way from oracle documentation link:
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 your threads are not completing with-in 120 seconds, you can change second if condition as :
while(!pool.awaitTermination(60, TimeUnit.SECONDS)) {
Thread.sleep(60000);
}
You can find other alternatives at # wait until all threads finish their work in java
One more key note on usage of isTerminated:
boolean isTerminated()
Returns true if all tasks have completed following shut down. Note that isTerminated is never true unless either shutdown or shutdownNow was called first.
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.
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.
I'd like to make a 2 threaded application like the following:
Create 2 threaded pool
Run a foo method on the #1 thread
Wait 2 seconds
Run bar method on #2 thread
The 2 threaded pool should wait a maximum of 20 seconds
ExecutorService executor = Executors.newFixedThreadPool(2);
executor.submit(() -> foo());
executor.awaitTermination(2, TimeUnit.SECONDS);
executor.submit(() -> bar());
if (!executor.awaitTermination(20, TimeUnit.SECONDS))
executor.shutdownNow();
It's not working, what can be wrong?
Great question! I do not think you have a clear understanding of the awaitTermination() method. Lets take a look at this document.
Blocks until all tasks have completed execution after a shutdown request, or the timeout occurs, or the current thread is interrupted, whichever happens first.
The awaitTermination() should not be used to wait for all tasks to complete. If that is the semantic you are looking for, utilize invokeAll() to block until all tasks have finished. Utilization of awaitTermination() without a prior shutdown() is improper and could cause you to wait for a while due to awaitTermination not shutting down the executor.
In this scenario, you are simply attempting to force the application to wait for your thread to finish, but if it does not in your allotted time frame you want to continue. This specific case makes me question the use of multi-threading a bit because it seems a bit overly designed, but for educational purposes lets explain how one could do this.
Basic Solution
ExecutorService executor = Executors.newFixedThreadPool(2);
executor.submit(() -> foo());
// Thread.sleep(2000); // Wait for 2 seconds
TimeUnit.SECONDS.sleep(2); // Also waits for 2 seconds and a bit more readable
executor.submit(() -> bar());
if (!executor.awaitTermination(20, TimeUnit.SECONDS))
executor.shutdownNow();
Although this is not ideal code, it will give you the semantics you are seeking.
Improvement
The executor.submit() will return a Future<T> object. This is a very strong object in Java and has a lot of capabilities. Lets see how we can improve the scenario .
ExecutorService executor = Executors.newFixedThreadPool(2);
Future<T> foo = executor.submit(() -> foo());
T result = foo.get(2, TimeUnit.SECONDS); // Attempt to grab the result for 2 seconds, then move on
executor.submit(() -> bar());
if (!executor.awaitTermination(20, TimeUnit.SECONDS))
executor.shutdownNow();
Now, this is much more proper code and will give you the desired semantics with better code structure. Additionally, it will unblock early if the first future completes before 2 seconds, a bit of an improvement from the basic solution!
Proper Shutdown
Assuming you want to wait for 20 seconds for the executor to finish, here is what you could do as an additional improvement. Utilize the below code for shutdown as it is from the documentation of ExecutorService as an example of shutdown. Here, I have updated your wait period to 20 seconds.
pool.shutdown(); // Disable new tasks from being submitted
try {
// Wait a while for existing tasks to terminate
if (!pool.awaitTermination(20, TimeUnit.SECONDS)) {
pool.shutdownNow(); // Cancel currently executing tasks
// Wait a while for tasks to respond to being cancelled
if (!pool.awaitTermination(20, 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();
}
What about using a scheduled executor service? You want to run task a, you want to run task b and you want to shutdown the executor service after 20 seconds.
ScheduledExecutorService service = Executors.newScheduledThreadPool(2);
Future<?> futureA = service.submit(()->foo());
ScheduledFuture<?> futureB = service.schedule(()->bar(), 2, TimeUnit.SECONDS);
I don't know why you want to shutdown the executor, but you can use the future to await the completion of the task.
Object b = futureB.get(20, TimeUnit.SECONDS);
service.shutdown();
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 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.