ExecutorService shutdown()和shutdownNow()方法區別

zhong0316發表於2019-03-03

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執行緒有許可權,否則拋異常),該執行緒並不一定會立馬退出:

  1. 如果執行緒處於被阻塞狀態(例如處於sleep, wait, join 等狀態),那麼執行緒立即退出被阻塞狀態,並丟擲一個InterruptedException異常。
  2. 如果執行緒處於正常的工作狀態,該方法只會設定執行緒的一個狀態位為true而已,執行緒會繼續執行不受影響。如果想停止執行緒執行可以在任務中檢查當前執行緒的狀態(Thread.isInterrupted())自己實現停止邏輯。

相關文章