java中的executor是什么 線程池Executor的4種創建方式

executor在Java中扮演線程管理和任務調度的核心角色,它解耦了任務提交與執行機制。1. newfixedthreadpool創建固定大小線程池,適用于任務數量穩定且對響應時間有要求的場景;2. newcachedthreadpool創建可動態調整大小的線程池,適合處理大量短期任務;3. newsinglethreadexecutor創建單線程池,保證任務順序執行;4. newscheduledthreadpool創建支持定時和周期性任務的線程池。但不推薦使用executors直接創建線程池,因可能引發oom問題,建議通過threadpoolexecutor自定義,其參數包括核心線程數、最大線程數、空閑線程存活時間、任務隊列、線程工廠及拒絕策略。關閉線程池時應優先調用shutdown()并配合awaittermination()確保任務完成,必要時再調用shutdownnow()強制關閉。

java中的executor是什么 線程池Executor的4種創建方式

Executor在Java中扮演著線程管理和任務調度的核心角色,它允許我們將任務的提交與任務的執行機制解耦。簡單來說,Executor就是一個執行Runnable任務的對象,它隱藏了線程創建和管理的復雜性,讓開發者可以專注于業務邏輯。

java中的executor是什么 線程池Executor的4種創建方式

線程池Executor的4種創建方式

java中的executor是什么 線程池Executor的4種創建方式

Executors.newFixedThreadPool(int nThreads)

這是最常見的線程池創建方式之一。它創建一個固定大小的線程池,池中的線程數量始終保持不變。如果所有線程都在忙碌,新提交的任務將在隊列中等待,直到有線程空閑出來。

立即學習Java免費學習筆記(深入)”;

java中的executor是什么 線程池Executor的4種創建方式

  • 優點: 資源消耗可控,響應速度快,適用于任務數量相對穩定,對響應時間有要求的場景。
  • 缺點: 如果任務提交速度遠大于處理速度,隊列可能會無限增長,導致內存溢出。
ExecutorService executor = Executors.newFixedThreadPool(10); for (int i = 0; i < 100; i++) {     executor.execute(() -> {         try {             Thread.sleep(100); // 模擬耗時操作         } catch (InterruptedException e) {             e.printStackTrace();         }         System.out.println("Thread: " + Thread.currentThread().getName());     }); } executor.shutdown(); // 記得關閉線程池

Executors.newCachedThreadPool()

創建一個可緩存的線程池。線程池的大小是不固定的,可以根據任務的需要動態調整。如果沒有空閑線程,則創建新的線程;如果線程空閑時間超過一定閾值(默認60秒),則會被回收。

  • 優點: 可以充分利用系統資源,處理大量短期任務。
  • 缺點: 如果任務提交速度過快,可能會創建大量的線程,導致CPU占用率過高,甚至OOM。不太適合長時間運行且任務量持續較高的場景。
ExecutorService executor = Executors.newCachedThreadPool(); for (int i = 0; i < 100; i++) {     final int taskNum = i;     executor.execute(() -> {         try {             Thread.sleep(100);         } catch (InterruptedException e) {             e.printStackTrace();         }         System.out.println("Thread: " + Thread.currentThread().getName() + ", Task: " + taskNum);     }); } executor.shutdown();

Executors.newSingleThreadExecutor()

創建一個單線程的Executor。它確保所有的任務都按照提交的順序依次執行。

  • 優點: 保證任務的順序執行,避免并發問題。
  • 缺點: 性能較低,不適合處理大量并發任務。
ExecutorService executor = Executors.newSingleThreadExecutor(); for (int i = 0; i < 10; i++) {     final int taskNum = i;     executor.execute(() -> {         System.out.println("Thread: " + Thread.currentThread().getName() + ", Task: " + taskNum);     }); } executor.shutdown();

Executors.newScheduledThreadPool(int corePoolSize)

創建一個可以執行延遲任務或定時任務的線程池。

  • 優點: 可以方便地執行定時任務。
  • 缺點: 相對復雜,需要仔細配置參數。
ScheduledExecutorService executor = Executors.newScheduledThreadPool(5);  // 延遲1秒后執行 executor.schedule(() -> {     System.out.println("Delayed task executed."); }, 1, TimeUnit.SECONDS);  // 每隔2秒執行一次 executor.scheduleAtFixedRate(() -> {     System.out.println("Periodic task executed."); }, 0, 2, TimeUnit.SECONDS);  // 注意:ScheduledExecutorService通常需要手動關閉,否則程序可能不會退出 // executor.shutdown(); //  在適當的時候關閉

如何選擇合適的Executor?

選擇合適的Executor取決于具體的應用場景。例如,對于CPU密集型任務,可以考慮使用newFixedThreadPool,線程數量設置為CPU核心數+1。對于IO密集型任務,可以使用newCachedThreadPool,讓線程池根據需要動態調整大小。如果需要保證任務的順序執行,可以使用newSingleThreadExecutor。如果需要執行定時任務,可以使用newScheduledThreadPool。

為什么不推薦使用Executors直接創建線程池?

阿里巴巴Java開發手冊中建議不要使用Executors創建線程池,而是通過ThreadPoolExecutor的構造方法來創建。這是因為Executors提供的線程池在某些情況下可能會導致OOM。例如,newFixedThreadPool和newSingleThreadExecutor的LinkedBlockingQueue默認長度是Integer.MAX_VALUE,可能會積大量的請求,導致OOM。newCachedThreadPool雖然可以動態創建線程,但是如果沒有控制好線程的數量,也可能會導致OOM。

ThreadPoolExecutor的參數詳解

ThreadPoolExecutor是創建線程池的核心類。它的構造方法如下:

public ThreadPoolExecutor(int corePoolSize,                               int maximumPoolSize,                               long keepAliveTime,                               TimeUnit unit,                               BlockingQueue<Runnable> workQueue,                               ThreadFactory threadFactory,                               RejectedExecutionHandler handler)
  • corePoolSize: 核心線程數。線程池中始終保持的線程數量,即使它們是空閑的。
  • maximumPoolSize: 最大線程數。線程池中允許的最大線程數量。
  • keepAliveTime: 線程空閑時間。當線程池中的線程數量超過corePoolSize時,多余的空閑線程的存活時間。
  • unit: keepAliveTime的時間單位。
  • workQueue: 任務隊列。用于保存等待執行的任務。常見的隊列類型有LinkedBlockingQueue、ArrayBlockingQueue、SynchronousQueue等。
  • threadFactory: 線程工廠。用于創建新的線程。
  • handler: 拒絕策略。當任務隊列已滿且線程池中的線程數量達到maximumPoolSize時,新提交的任務將被拒絕。常見的拒絕策略有AbortPolicy(拋出異常)、CallerRunsPolicy(由調用者線程執行)、DiscardPolicy(直接丟棄)、DiscardOldestPolicy(丟棄隊列中最老的任務)。

如何優雅地關閉線程池?

關閉線程池通常有兩種方式:shutdown()和shutdownNow()。

  • shutdown(): 平滑關閉線程池,不再接受新的任務,但會等待所有已提交的任務執行完畢。
  • shutdownNow(): 立即關閉線程池,嘗試停止所有正在執行的任務,并返回等待執行的任務列表。

建議使用shutdown()方法,給線程池一個優雅關閉的機會。在關閉線程池之后,需要調用awaitTermination()方法等待所有任務執行完畢。

ExecutorService executor = Executors.newFixedThreadPool(10); // 提交任務...  executor.shutdown(); // 拒絕接受新的任務 try {     if (!executor.awaitTermination(60, TimeUnit.SECONDS)) {         executor.shutdownNow(); // 超時后強制關閉     } } catch (InterruptedException e) {     executor.shutdownNow();     Thread.currentThread().interrupt(); }

? 版權聲明
THE END
喜歡就支持一下吧
點贊13 分享