ExecutorService是我們經常使用的執行緒池,當我們使用完執行緒池後,需要關閉執行緒池。ExecutorService的shutdown()和shutdownNow()方法都可以用來關閉執行緒池,那麼他們有什麼區別呢?
廢話不多說,直接檢視原始碼,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.
*
* <p>This method does not wait for previously submitted tasks to
* complete execution. Use {@link #awaitTermination awaitTermination}
* to do that.
*
* @throws SecurityException if a security manager exists and
* shutting down this ExecutorService may manipulate
* threads that the caller is not permitted to modify
* because it does not hold {@link
* java.lang.RuntimePermission}{@code ("modifyThread")},
* or the security manager`s {@code checkAccess} method
* denies access.
*/
void shutdown();
複製程式碼
當我們呼叫shutdown()方法後,執行緒池會等待我們已經提交的任務執行完成。但是此時執行緒池不再接受新的任務,如果我們再向執行緒池中提交任務,將會拋RejectedExecutionException異常。如果執行緒池的shutdown()方法已經呼叫過,重複呼叫沒有額外效應。注意,當我們呼叫shutdown()方法後,會立即從該方法中返回而不會阻塞等待執行緒池關閉再返回,如果希望阻塞等待可以呼叫awaitTermination()方法。
再看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.
*
* <p>This method does not wait for actively executing tasks to
* terminate. Use {@link #awaitTermination awaitTermination} to
* do that.
*
* <p>There are no guarantees beyond best-effort attempts to stop
* processing actively executing tasks. For example, typical
* implementations will cancel via {@link Thread#interrupt}, so any
* task that fails to respond to interrupts may never terminate.
*
* @return list of tasks that never commenced execution
* @throws SecurityException if a security manager exists and
* shutting down this ExecutorService may manipulate
* threads that the caller is not permitted to modify
* because it does not hold {@link
* java.lang.RuntimePermission}{@code ("modifyThread")},
* or the security manager`s {@code checkAccess} method
* denies access.
*/
List<Runnable> shutdownNow();
複製程式碼
首先shutdownNow()方法和shutdown()方法一樣,當我們呼叫了shutdownNow()方法後,呼叫執行緒立馬從該方法返回,而不會阻塞等待。這也算shutdownNow()和shutdown()方法的一個相同點。與shutdown()方法不同的是shutdownNow()方法呼叫後,執行緒池會通過呼叫worker執行緒的interrupt方法盡最大努力(best-effort)去”終止”已經執行的任務。
而對於那些在堵塞佇列中等待執行的任務,執行緒池並不會再去執行這些任務,而是直接返回這些等待執行的任務,也就是該方法的返回值。
值得注意的是,當我們呼叫一個執行緒的interrupt()方法後(前提是caller執行緒有許可權,否則拋異常),該執行緒並不一定會立馬退出:
- 如果執行緒處於被阻塞狀態(例如處於sleep, wait, join 等狀態),那麼執行緒立即退出被阻塞狀態,並丟擲一個InterruptedException異常。
- 如果執行緒處於正常的工作狀態,該方法只會設定執行緒的一個狀態位為true而已,執行緒會繼續執行不受影響。如果想停止執行緒執行可以在任務中檢查當前執行緒的狀態(Thread.isInterrupted())自己實現停止邏輯。