76

What is the difference between

ExecutorService eService = Executors.newFixedThreadPool(2);
eService.execute(new TestThread6());
eService.execute(new TestThread6());
eService.execute(new TestThread6());
eService.awaitTermination(1, TimeUnit.NANOSECONDS);
eService.shutdown();

and

eService.shutdown();
eService.awaitTermination(1, TimeUnit.NANOSECONDS);

I don't really understand shutdown(). This method does not wait for previously submitted tasks to complete execution. Does it mean shutdown() may terminate the tasks which have been submitted, but not completed? I tried some examples, they do not prove it, please give me an example.

Ravindra babu
  • 37,698
  • 11
  • 250
  • 211
王奕然
  • 3,891
  • 6
  • 41
  • 62
  • 1
    Have a look at : https://stackoverflow.com/questions/36644043/how-to-properly-shutdown-java-executorservice/36644320#36644320 – Ravindra babu Aug 26 '17 at 17:48
  • There will be no termination until you issue the shutdown, which therefore has to come first. Surely this is obvious? If there was an auto-termination there would be no need for a shutdown API. – user207421 Aug 04 '23 at 09:29

10 Answers10

81

You should call shutdown first. Otherwise, you might be waiting for a very long time, since awaitTermination doesn't actually shut down your executor.

If you wanted to wait for tasks to complete, rather than wait for the executor to shut down, then you should use invokeAll.

C. K. Young
  • 219,335
  • 46
  • 382
  • 435
  • thanks,but why waiting for a very long time?could you give me some example to explain? – 王奕然 Aug 25 '13 at 02:24
  • 5
    @user2245634 `awaitTermination` doesn't actually shut down your executor first. So unless another thread shuts down the executor, `awaitTermination` will just sit there until the timeout runs out. Obviously, in your example, you were waiting only 1 nanosecond before timing out, which was why you didn't observe the "very long time". – C. K. Young Aug 25 '13 at 02:25
  • 1
    thanks,i understand,and in shutdown() api:This method does not wait for previously submitted tasks to complete execution. it means maybe shutdown() may terminate the task which have submited,but not complete?but i try some examples not prove it – 王奕然 Aug 25 '13 at 02:39
  • @user2245634 Correct, any incomplete tasks will be cancelled (their threads will be sent interrupts). If your tasks don't check for interrupts, however, then of course cancellation won't work. – C. K. Young Aug 25 '13 at 02:49
  • please look this code public class TestThread9 implements Runnable{ @Override public void run() { if (Thread.interrupted()) { System.out.println("interrupted"); return; } System.out.println("a"); } public static void main(String[] args) throws InterruptedException { ExecutorService eService = Executors.newFixedThreadPool(2); eService.execute(new TestThread9()); eService.execute(new TestThread9()); eService.shutdown(); } }in this example,i only call shutdown(),not call awaitTermination ,and i check interrupt but not "interrupted" was print – 王奕然 Aug 25 '13 at 03:11
  • @user2245634 Your task finished before it was interrupted. Try doing something like: `while (!Thread.interrupted()) {System.out.println("loop"); Thread.sleep(1000);}`. You will see results. – C. K. Young Aug 25 '13 at 03:26
  • i try use your code,and call shutdown(),but never terminate,and print "loop" forever:public class TestThread9 implements Runnable{ @Override public void run() { while (!Thread.interrupted()) {System.out.println("loop"); try { Thread.sleep(1000); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); }} } public static void main(String[] args) throws InterruptedException { ExecutorService eService = Executors.newFixedThreadPool(2); eService.execute(new TestThread9()); eService.execute(new TestThread9()); eService.shutdown(); } – 王奕然 Aug 25 '13 at 04:55
  • 25
    Note that `shutdown()` does not interrupt already executing tasks. From javadoc : "Initiates an orderly shutdown in which previously submitted tasks are executed, but no new tasks will be accepted." If you want interruption you should call `shutDownNow()`. – bowmore Aug 25 '13 at 08:32
  • @user2245634 What bowmore said. (Just said that to highlight your name, so you get notified.) – C. K. Young Aug 25 '13 at 12:18
  • shutdown terminates all the threads and awaitTermination after shutdown is redundant. – Amrish Pandey Jul 01 '15 at 14:54
  • 2
    @AmrishPandey No, that's not what the documentation says. See S.D.'s answer. What you describe is what shutdownNow does. – Yngvar Kristiansen Jul 29 '16 at 08:26
  • The ideal construct is shutdown() ; followed by if(!awaitTermination) -> shutdownNow() – Achow Feb 19 '21 at 04:52
57

Reading the documentation always helps:

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. These tasks are drained (removed) from the task queue upon return from this method.

This method does not wait for actively executing tasks to terminate. Use awaitTermination to do that.

There are no guarantees beyond best-effort attempts to stop processing actively executing tasks. This implementation cancels tasks via Thread.interrupt(), so any task that fails to respond to interrupts may never terminate

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.

awaitTermination:

Blocks until all tasks have completed execution after a shutdown request, or the timeout occurs, or the current thread is interrupted, whichever happens first.

S.D.
  • 29,290
  • 3
  • 79
  • 130
  • 26
    I do not understand the documentation for shutdown. It first says "previously submitted tasks are executed" and then it says "this method does not wait for previously submitted tasks to complete execution." So, will my tasks run to completion or not? – jmrah Feb 12 '17 at 01:10
  • 32
    @jrahhali It means method call returns immediately. I.e. the thread that calls `shutdown` does not blocks. – S.D. Feb 13 '17 at 07:55
  • 16
    Ahh, does not block. That makes sense now. They should've used that word instead of wait. Thanks. – jmrah Feb 13 '17 at 13:48
  • 1
    One slight modification on @S.D.'s answer. Where they say that "`shutdown` does not wait for previously submitted tasks to complete execution", I believe they mean that the current thread does _not_ **block** until the previously submitted tasks complete execution. – Jason Nov 29 '21 at 21:26
24

shutdown means the executor service takes no more incoming tasks.

awaitTermination is invoked after a shutdown request.

You need to first shut down the service and then block and wait for threads to finish.

If you want to see all threads finish running and insist on using awaiTermination, you need to set the timeout parameter to be big enough. So you could do:

eService.shutdown();
if (!eService.awaitTermination(60000, TimeUnit.SECONDS))
    System.err.println("Threads didn't finish in 60000 seconds!");
}

Alternatively, you could do:

eService.shutdown();
while (!eService.isTerminated()) {

}

This way you are able to ensure all threads are finished running unless they are interrupted unexpectedly.

Terry Li
  • 16,870
  • 30
  • 89
  • 134
  • 2
    you probably meant milliseconds... 60000s is 16.666 hours. – Peter Perháč Dec 16 '15 at 00:19
  • 34
    Don't do a busy-wait like the second code snippet. Just. Don't. – Alexander Feb 11 '16 at 19:51
  • the last code block is what I came for. Thank u so much – ahrooran Jul 11 '21 at 15:41
  • 2
    @ahrooran as @Alexander noted, you should not use the second block. That kind of empty-bodied `while` loop is known as "busy-wait" and will keep a CPU core at 100% until it completes. That is a waste given that you have the `awaitTermination` method available. – Igor Rodriguez Jul 23 '21 at 10:14
  • 1
    @IgorRodriguez true. But I need that last juice of performance out of the system. I had to benchmark a program – ahrooran Jul 24 '21 at 08:09
  • Add some polling for the 2nd example to limit the number of cycles – downvoteit Aug 18 '21 at 14:19
  • 1
    @ahrooran but the second one does not guarantee better performance. Your Threadpool usually has enough threads to keep all CPUs busy. When calling awaitTermination the join() Operations of the Threads will block your main Thread until all the Executor Threads are completed, so that it does not waste CPU resources that are better used calculating your result. Thanks to interrupts, the Main Thread will immediately be woken up when the threads have terminated, the timelimit is just an upper bound. – Frobeniusnorm Feb 18 '23 at 16:33
13

The best implementation:

executor.shutdown();
try {
    if (!executor.awaitTermination(3500, TimeUnit.MILLISECONDS)) {
        executor.shutdownNow();
    }                   
} catch (InterruptedException e) {              
    executor.shutdownNow();
}
        
informatik01
  • 16,038
  • 10
  • 74
  • 104
Xavy Guzman
  • 131
  • 1
  • 3
  • 1
    This answer is exactly what I was looking for. Could perhaps use some more explanation as to what is going on though. – hayden.mumm Aug 02 '23 at 20:46
10

Main Difference

shutdown()-

1. Doesn't block the calling a thread i.e. the thread who called the shutdown().
2. Excecutor doesn't accept any new task after calling shutdown().

awaitTermination() -

1. Blocks the calling thread. (as join() method do)

Point of Confusion:- If shutdown() does not kill the previously submitted tasks, why do we need awaitTermination()?

awaitTermination means waiting for the tasks to be completed/terminated, right? shutdown() is doing the same- waiting for any task which is already submitted along with the running tasks to continue till completed/terminated, then why another method awaitTermination(..)? Below is the explanation:

Suppose you can wait for 10 min only to complete all the task that are submitted and after that want to call shutdownNow()(---you already know what it do) then use awaitTermination(long timeout, TimeUnit unit) after calling shutdown().

Notice the method arguments in awaitTermination(long timeout, TimeUnit unit). This timeout is the key here.

If there is no time restriction, shutdown() is OK. No need of awaitTermination().

Dexter
  • 4,036
  • 3
  • 47
  • 55
Ashwani Tiwari
  • 1,497
  • 18
  • 28
  • 1
    IMHO, instead of awaitTermination(long timeout, TimeUnit unit), shutdown(long timeout, TimeUnit unit) would have been less confusing. Then would not have to call shutdown() first, then awaitTermination(..). Can any one enlighten on the logic behind a separate method instead of overloading shutdown() ? – Dexter Sep 10 '20 at 15:54
  • What if awaitTermination exit the block and there are still tasks running? How do you make sure all the task in the pool are terminated/killed (if timeout is reached) before proceeding? – n1nsa1d00 Nov 16 '21 at 15:08
  • As I mentioned in answer, we just call awaitTermination before calling shutdownNow(), giving some time to task in pool to execute or complete. If they not completed in the given time , you will shutdown the executor – Ashwani Tiwari Nov 16 '21 at 15:45
  • Isn't _awaitTermination()_ useless if used after _shutdown()_? – Buffalo Nov 10 '22 at 10:16
3

After we start the first task ThreadPoolExecutor will start a Thread that will not end even after the task is finished. At least it's true for a fixed thread pool. This is why we need to call shutdown. After shutdown ThreadPoolExecutor will reject any new task but will wait for running tasks to finish and then allow the Threads to end. This is why we need awaitTermination after shutdwon.

Evgeniy Dorofeev
  • 133,369
  • 30
  • 199
  • 275
3
executorService.execute(runnableTask);  

//executorService.shutdown(); //it will make the executorService stop accepting new tasks
//executorService.shutdownNow(); //tires to destroy the executorService immediately, but it doesn't guarantee that all the running threads will be destroyed at the same time. This method returns list of tasks which are waiting to be processed.
//List<Runnable> notExecutedTasks = executorService.shutdownNow(); //this method returns list of tasks which are waiting to be processed.developer decide what to do with theses tasks?

//one good way to shutdown the executorService is use both of these methods combined with the awaitTermination
executorService.shutdown();
try{
    if(!executorService.awaitTermination(1000, TimeUnit.MICROSECONDS)) {
        executorService.shutdownNow();
    }
}catch (InterruptedException e){
    e.printStackTrace();
}
HansHirse
  • 18,010
  • 10
  • 38
  • 67
0

From Java8 ThreadPool awaitTermination method:

    try {
        for (;;) {
            if (runStateAtLeast(ctl.get(), TERMINATED))
                return true;
            if (nanos <= 0)
                return false;
            nanos = termination.awaitNanos(nanos);
        }
    } finally {
        mainLock.unlock();
    }

It will first check run state of thread pool. And if the thread pool is not shut down(which set run state to terminated), awaitTermination method will not return until timeout. This explains why await a long time if you await first then shutdown.

Gawain
  • 1,017
  • 8
  • 17
0

shutdown() will stop the executor from taking anymore tasks and lets the tasks which are in execution to complete. The call won't block the current Thread.

awaitTermination(1, TimeUnit.NANOSECONDS) will wait for the executor to complete the execution for that given amount of time. Note, it is a blocking call.

If your priority is to let the executor complete its execution before terminating, then a simple call to shutdown() will do the job.

However, in some scenarios we might want to shutdown the executor after a given period of time, regardless of the tasks completing its execution. For those scenarios you can have something like below:

Runnable runnable = () -> System.out.println("Some tasks.");
ExecutorService eService = Executors.newFixedThreadPool(2);
eService.execute(runnable);
eService.execute(runnable);
eService.execute(runnable);
eService.execute(runnable);

eService.shutdown();
try {
    int waitCount = 0;
    // blocking the Thread for 1 minute. If awaitTermination() returns true then executor is shutdown
    while (!eService.awaitTermination(1, TimeUnit.MINUTES)) {
        waitCount++;
        if (waitCount == 60) { // waited for 60 minutes to complete execution
            List<Runnable> runnableList = eService.shutdownNow();
            System.out.println("ThreadPool forcefully shutdown with " + runnableList.size() + " tasks remaining.");
            break;
        }

    }
} catch (InterruptedException e) {
    eService.shutdownNow();
    System.err.println("ThreadPool shutdown interrupted.");
    Thread.currentThread().interrupt();
}
sam
  • 1,800
  • 1
  • 25
  • 47
-2

You need to call shutdownNow() method after the awaitTermination() method call happened. Then only you can find out the actual usage of awaitTermination() method.

Cà phê đen
  • 1,883
  • 2
  • 21
  • 20
user3094331
  • 532
  • 6
  • 21