線程池 (thread pool) 的類型與實現方式

 

  在許多應用中須要頻繁的建立許多生命週期很短的線程,若是用傳統方法的話就會形成大量的資源了浪費,java的設計者們考慮到了這點在java中加入了線程池這個特性,它負責管理大量的線程的建立銷燬等操做。java

  首先咱們須要瞭解一個類:java.util.concurrent.Executors(執行器)api

  執行器類擁有大量的靜態工廠方法用於建立線程池ide

  

方法 描述
newCachedThreadPool 必要時建立線程,處於空閒狀態的線程將被保留60秒
newFixedThreadPool 擁有固定數量的線程,而且不會自動銷燬空閒狀態的線程
newSingleThreadExecutor 該線程池僅有一個線程,會順序執行任務隊列
newScheduledThreadPool 用於預定執行任務的固定線程池
newSingleThreadScheduledExecutor  用於預定執行任務的單線程池

 

 下面咱們來詳細瞭解下這些線程池。spa

 

  newCachedThreadPool:經過名稱,不難看出這個方法建立出的線程池,具備數量可變,而且在須要的時候會自動建立更多的線程,而且會自動銷燬線程線程

  newFixedThreadPool:此線程池與newCachedThreadPool構建出的線程池的主要區別是,線程池在數量上固定,如果任務數量達到上限的話,就會將多餘任務加入任務隊列,等線程池空出線程時便可執行,這種線程池並不會銷燬空閒線程。  設計

  newSingleThreadExecutor:此方法建立出的線程池相較於其餘兩個線程較爲特殊,此方法建立出的線程數量僅僅爲1,也就是說全部除了正在執行的任務外,其他任務均在任務隊列中,當線程中的任務執行完畢後,任務隊列的第一個任務進入線程開始執行code

  newScheduledThreadPool與 newSingleThreadScheduledExecutor:這兩個方法建立出的線程池是用於預約執行的線程池,他們能夠用於在初始化後延遲執行,或週期性的執行,兩種線程池大致相同,惟一的區別就是可同時執行的線程數量對象

 

  當挑選完的線程池後就須要建立以及使用線程池:生命週期

    大概步驟爲如下3步:隊列

                (1)調用執行器類(Executors)的靜態方法來建立線程池

                (2)調用線程池的submit方法提交Runnable或Callable對象

                (3)當不須要添加更多的任務時,調用shutdown關閉入口

  下面經過代碼來逐步操做:

    

//建立線程池對象
        ExecutorService service = Executors.newCachedThreadPool();
        //建立一個用於遞增輸出i值的runnable對象
        Runnable runnable = new Runnable() {
            @Override
            public void run() {
                for (int i = 0; i < 400; i++) {
                    System.out.println(i);
                }
            }
        };
        //調用線程池的submit方法傳入runnable(傳入的runnable將會自動執行)
        service.submit(runnable);
        service.submit(runnable);
        //當不須要傳入更多的任務時調用shutdown方法來關閉入口
        service.shutdown();

 

 

    須要注意的是若是但願直接中止線程池的一切任務是沒法經過shutdown來操做的,由於shutdown僅僅是關閉了入口,可是已經加入的任務仍是會繼續執行的,這時咱們能夠調用線程池的shutdownNow方法來操做,shutdownNow的做用是用來關閉線程池的入口而且會嘗試終止全部當前線程池內的任務。

//用來關閉線程池入口以及終止全部正在執行的任務
  service.shutdownNow();

   service的submit方法會返回一個Future<?>類型的對象,然而這是一個怎樣的類型呢?讓咱們來看一下api中的方法摘要:

 

   

 

   從方法摘要中能夠看出該對象用於在加入線程池之後可以對此任務進行取消,查看狀態等操做,若是說在加入線程池之後有可能會取消此任務的話就須要,在submit的時候就須要保存好Future對象。

 

     //保存Future<?>
        Future<?> run2 = service.submit(runnable);
        
        //用於查看是否已經執行完畢,返回類型爲boolean
        System.out.println(run2.isDone());
        
        //取消任務,若是須要中斷的話參數爲true
        run2.cancel(true);

 

   關於線程池的簡單操做大概就有這些.

相關文章
相關標籤/搜索