Java:超簡單 Thread Pool 功能實作
介紹 Thread Pool 之前,我們要先搞清楚 Thread 是什麼。
因為內容很多,所以這邊引用修改了 Program,Process,Thread 的資料:
嗯,好像有點扯太遠了,
總之Thread 執行緒常被定義為一個輕量的(Lightweight) Process,可用來處理 request,
然而雖然是輕量,但在產生 Thread 時仍會有 overhead,此時若 request 量太大,
又沒有善加管理這些 Thread 的話,就會拖累整體系統的效能。
為了解決這種類型的效能問題,所以就有了 Thread Pool 的概念產生。
Thread Pool 的概念如同其名,就是一個 Thread 的 Pool,
其中有固定或變動量的 Thread,當 request 進來時,若有閒置的 Thread 就執行,
若沒有的話,可能產生新的 Thread 或把 request 放入 queue 中等待被執行,
當一條 Thread 執行完工作而 queue 中仍有 request 在等待時,
此 Thread 應該要被分發新的 request 並處理。
由以上幾行,我們可以看出 Thread Pool 的工作有:
若有興趣的人可以參考Design Pattern: Thread Pool 模式,
看看以前是怎麼實作 Thread Pool,以往用 Java 寫 Thread Pool 並不是簡單的事,
不過在 JavaSE 5.0 後,只要用簡單的幾行程式碼就可以做出 Thread Pool 的效果:
Thread Pool 的 Thread 生命週期、request queue、分發request 都被 Java 做掉了,
我們所要做的就只有設定 Thread 的數量和專注在工作的內容,是不是相當簡單呢?
另外除了固定 Thread 數量的 Thread Pool 可用 Executors.newFixedThreadPool() 外,
Executors 也提供了其他的 method 來產生不同的 Thread Pool,如:
也可以參考 java.util.concurrent.ThreadPoolExecutor 建立符合自己需求的 Thread Pool。
關鍵字:Java, Thread, Pool, Executor, Executors, ThreadExecutor, ThreadPoolExecutor
參考資料:
因為內容很多,所以這邊引用修改了 Program,Process,Thread 的資料:
- Program:
一群程式碼的集合,用以解決特定的問題。在物件導向中相當於類別(Class)。 - Process:
由Program所產生的執行個體,一個Program可以同時執行多次產生多個Process。在物件導向中相當於Object。
- Memory Space:相當於Object的variable,不同Process的Memory Space也不同,彼此看不到其他Process的Memory Space。
- 一個以上的Thread:
Thread代表從某個起始點開始(例如main),到目前為止所有函數的呼叫路徑,以及這些呼叫路徑上所用到的區域變數。
- Stack:紀錄函數呼叫路徑,以及這些函數所用到的區域變數。
- 目前CPU的狀態。
嗯,好像有點扯太遠了,
總之Thread 執行緒常被定義為一個輕量的(Lightweight) Process,可用來處理 request,
然而雖然是輕量,但在產生 Thread 時仍會有 overhead,此時若 request 量太大,
又沒有善加管理這些 Thread 的話,就會拖累整體系統的效能。
為了解決這種類型的效能問題,所以就有了 Thread Pool 的概念產生。
Thread Pool 的概念如同其名,就是一個 Thread 的 Pool,
其中有固定或變動量的 Thread,當 request 進來時,若有閒置的 Thread 就執行,
若沒有的話,可能產生新的 Thread 或把 request 放入 queue 中等待被執行,
當一條 Thread 執行完工作而 queue 中仍有 request 在等待時,
此 Thread 應該要被分發新的 request 並處理。
由以上幾行,我們可以看出 Thread Pool 的工作有:
- 管控 Thread 的產生與回收
- 分發 Thread 處理 request
- 處理 request 的 queue
若有興趣的人可以參考Design Pattern: Thread Pool 模式,
看看以前是怎麼實作 Thread Pool,以往用 Java 寫 Thread Pool 並不是簡單的事,
不過在 JavaSE 5.0 後,只要用簡單的幾行程式碼就可以做出 Thread Pool 的效果:
1 package demo; 2 3 import java.util.concurrent.Executor; 4 import java.util.concurrent.Executors; 5 6 public class ThreadPoolDemo { 7 8 public static void main(String[] args) { 9 10 // 建立 2 個 thread 的 thread pool 11 Executor executor = Executors.newFixedThreadPool(2); 12 13 // 執行實作了 Runnable 介面的內部類別 Work 14 executor.execute(new Work(1)); 15 executor.execute(new Work(2)); 16 executor.execute(new Work(3)); 17 18 // 直接在 function 中宣告匿名內部類別 19 executor.execute(new Runnable() { 20 // anonymous inner class 21 @Override 22 public void run() { 23 System.out.println(Thread.currentThread().getName() + 24 " Begins Work in anonymous inner class."); 25 } 26 }); 27 } 28 29 public static class Work implements Runnable { 30 private int id; 31 32 public Work (int id) { 33 this.id = id; 34 } 35 36 public void run() { 37 System.out.println(Thread.currentThread().getName() + 38 " Begins Work " + id); 39 try { 40 Thread.sleep(5000); 41 } 42 catch (InterruptedException ex) { 43 ex.printStackTrace(); 44 } 45 System.out.println(Thread.currentThread().getName() + 46 " Ends Work " + id); 47 } 48 } 49 } 執行結果如下: pool-1-thread-2 Begins Work 2 pool-1-thread-1 Begins Work 1 pool-1-thread-1 Ends Work 1 pool-1-thread-1 Begins Work 3 pool-1-thread-2 Ends Work 2 pool-1-thread-2 Begins Work in anonymous inner class. pool-1-thread-1 Ends Work 3由以上的程式中我們可以發現,
Thread Pool 的 Thread 生命週期、request queue、分發request 都被 Java 做掉了,
我們所要做的就只有設定 Thread 的數量和專注在工作的內容,是不是相當簡單呢?
另外除了固定 Thread 數量的 Thread Pool 可用 Executors.newFixedThreadPool() 外,
Executors 也提供了其他的 method 來產生不同的 Thread Pool,如:
- newSingleThreadExecutor()
- newCachedThreadPool()
- newScheduledThreadPool()
- newSingleThreadScheduledExecutor() 等
也可以參考 java.util.concurrent.ThreadPoolExecutor 建立符合自己需求的 Thread Pool。
關鍵字:Java, Thread, Pool, Executor, Executors, ThreadExecutor, ThreadPoolExecutor
參考資料: