Java多線程——<三>簡單的線程執行:Executor


一、概述

  按照《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》,內容均來自個人理解與總結,如有理解錯誤,請大家批評指正

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM