一、概述
按照《Java多線程——<一><二>》中所講,我們要使用線程,目前都是顯示的聲明Thread,並調用其start()方法。多線程並行,明顯我們需要聲明多個線程然后都調用他的start方法,這么一看,似乎有些問題:第一、線程一旦多了,聲明勢必是個問題;第二、多線程啟動如果通過手動執行的話,那可能一個線程已經跑完了,另外一個還沒起來(我推測可能會出現這個問題)。所以,我們在想,如果有個管家,能夠幫我們管理這么多線程,只需要把我們定義的任務交給管家,管家就能夠幫我們把任務附着到線程上,並且當我們給管家發送指令讓所有的線程開始並發執行時,他也能夠幫助我們開啟所有線程執行。
二、java多線程管家——Executor
Executor允許你管理異步任務的執行,而無須顯示地管理線程的生命周期。ExecutorService知道如何構建恰當的上下文來執行Runnable對象。
1.創建ExecutorService
通過Executors能夠創建兩種方式的ExectorService。第一種、CachedThreadPool會為每個傳入的任務新創建一個線程
ExecutorService exec = Executors.newCachedThreadPool();
第二種、FixedThreadPool可以一次性預先執行代價高昂的線程分配,所以可以用來限制線程的數量。這可以節省時間,因為你不必為每個任務都固定的付出創建線程的開銷。
ExecutorService exeService = Executors.newFixedThreadPool(5);
2.把任務附着給ExecutorService
有了executor,你只需要定義任務並將任務對象傳遞給executor即可。
exeService.execute(new Task());
3.讓所有任務開始執行
這兩個方法會讓之前提交到該exectuor的所有任務開始執行。為了避免啟動后,會被注入新的任務,必須在你將所有線程注入后,執行關閉操作以保證這一點。
exeService.shutdown();
總結:
|——原來:想執行任務
| | |——1.定義任務
| | |——2.創建任務對象交由Thread對象操縱
| | |——3.顯示的調用Thread對象的start()方法
| |——遇到問題:比較繁瑣,總得自己啟動線程調用;本質上是由main函數調用的
|——現在:使用java.util.concurrent.Executor(執行器)來管理Thread對象
| | |——1.ExecutorService exec = Executors.newAcahedThreadPool();
| | |——2.exec.execute(new Task());
| | |——3.exec.shutdown();
| |——在客戶端(顯示調用線程執行)和執行任務之間提供了一個間接層,用以執行任務;撇開了main函數,由executor直接進行了調用
| |——允許你管理異步任務的執行,而無須顯示地管理線程的生命周期
三、其他
1.何時使用哪種線程池呢?
CachedThreadPool在程序執行過程中通常會創建與所需數量相同的線程,然后在它回收舊線程時停止創建新線程,因此它是合理的Executor的首選
只有當這種方式會引起問題時,才需要切換到FixedThreadPool。
2.SingleThreadExecutor
SingleThreadExecutor就像是線程數量為1的FixedThreadPool
|——在另一個線程中連續運行的任何事務來說都很有用(重點是連續運行,因為這樣可以順序接受處理),故SingleThreadPool會序列化所有提交給它的任務, 並會維護它自己隱藏的懸掛任務隊列
|——例如:向SingleThreadExecutor提交多個任務,那么這些任務將排隊,每個任務都會在下一個任務開始之前運行結束,所有任務使用相同線程。
3.自定義線程工廠
每個靜態的ExecutorService創建方法都被重載為接受一個ThreadFactory對象,該對象將被用來創建新的線程。例如:
public class TaskDaemonFactory implements ThreadFactory{ public Thread newThread(Runnable r){ Thread t = new Thread(r);return t; } }
想使用自己定義的線程工廠
ExecutorService exec = Executors.newCachedThreadPool(new TaskDaemonFactory());
這樣可以通過具體的要求來改造線程。
注:以上代碼均來自《Thinking in java》,內容均來自個人理解與總結,如有理解錯誤,請大家批評指正