5-線程池

 

線程池

什麼是線程池

Java中的線程池是運用場景最多的併發框架,幾乎全部須要異步或併發執行任務的程序
均可以使用線程池。在開發過程當中,合理地使用線程池可以帶來3個好處。
第一:下降資源消耗。經過重複利用已建立的線程下降線程建立和銷燬形成的消耗。
第二:提升響應速度。當任務到達時,任務能夠不須要等到線程建立就能當即執行。
第三:提升線程的可管理性。線程是稀缺資源,若是無限制地建立,不只會消耗系統資源,
還會下降系統的穩定性,使用線程池能夠進行統一分配、調優和監控。可是,要作到合理利用
線程池,必須對其實現原理了如指掌。java

線程池做用

線程池是爲忽然大量爆發的線程設計的,經過有限的幾個固定線程爲大量的操做服務,減小了建立和銷燬線程所需的時間,從而提升效率。程序員

若是一個線程的時間很是長,就不必用線程池了(不是不能做長時間操做,而是不宜。),何況咱們還不能控制線程池中線程的開始、掛起、和停止。緩存

線程池的分類

ThreadPoolExecutor

Java是天生就支持併發的語言,支持併發意味着多線程,線程的頻繁建立在高併發及大數據量是很是消耗資源的,由於java提供了線程池。在jdk1.5之前的版本中,線程池的使用是及其簡陋的,可是在JDK1.5後,有了很大的改善。JDK1.5以後加入了java.util.concurrent包,java.util.concurrent包的加入給予開發人員開發併發程序以及解決併發問題很大的幫助。這篇文章主要介紹下併發包下的Executor接口,Executor接口雖然做爲一個很是舊的接口(JDK1.5 2004年發佈),可是不少程序員對於其中的一些原理仍是不熟悉,所以寫這篇文章來介紹下Executor接口,同時鞏固下本身的知識。若是文章中有出現錯誤,歡迎你們指出。多線程

Executor框架的最頂層實現是ThreadPoolExecutor類,Executors工廠類中提供的newScheduledThreadPool、newFixedThreadPool、newCachedThreadPool方法其實也只是ThreadPoolExecutor的構造函數參數不一樣而已。經過傳入不一樣的參數,就能夠構造出適用於不一樣應用場景下的線程池,那麼它的底層原理是怎樣實現的呢,這篇就來介紹下ThreadPoolExecutor線程池的運行過程。併發

 

corePoolSize: 核心池的大小。 當有任務來以後,就會建立一個線程去執行任務,當線程池中的線程數目達到corePoolSize後,就會把到達的任務放到緩存隊列當中
maximumPoolSize: 線程池最大線程數,它表示在線程池中最多能建立多少個線程;
keepAliveTime: 表示線程沒有任務執行時最多保持多久時間會終止。
unit: 參數keepAliveTime的時間單位,有7種取值,在TimeUnit類中有7種靜態屬性:框架

線程池四種建立方式

Java經過Executors(jdk1.5併發包)提供四種線程池,分別爲:
newCachedThreadPool建立一個可緩存線程池,若是線程池長度超過處理須要,可靈活回收空閒線程,若無可回收,則新建線程。異步

案例演示:jvm


newFixedThreadPool 建立一個定長線程池,可控制線程最大併發數,超出的線程會在隊列中等待。
newScheduledThreadPool 建立一個定長線程池,支持定時及週期性任務執行。
newSingleThreadExecutor 建立一個單線程化的線程池,它只會用惟一的工做線程來執行任務,保證全部任務按照指定順序(FIFO, LIFO, 優先級)執行。ide

newCachedThreadPool

建立一個可緩存線程池,若是線程池長度超過處理須要,可靈活回收空閒線程,若無可回收,則新建線程。示例代碼以下:函數

            // 無限大小線程池 jvm自動回收

            ExecutorService newCachedThreadPool = Executors.newCachedThreadPool();

            for (int i = 0; i < 10; i++) {

                  final int temp = i;

                  newCachedThreadPool.execute(new Runnable() {

 

                       @Override

                       public void run() {

                             try {

                                   Thread.sleep(100);

                             } catch (Exception e) {

                                   // TODO: handle exception

                             }

                             System.out.println(Thread.currentThread().getName() + ",i:" + temp);

 

                       }

                  });

            }

 

總結: 線程池爲無限大,當執行第二個任務時第一個任務已經完成,會複用執行第一個任務的線程,而不用每次新建線程。

newFixedThreadPool

建立一個定長線程池,可控制線程最大併發數,超出的線程會在隊列中等待。示例代碼以下:

ExecutorService newFixedThreadPool = Executors.newFixedThreadPool(5);

            for (int i = 0; i < 10; i++) {

                  final int temp = i;

                  newFixedThreadPool.execute(new Runnable() {

 

                       @Override

                       public void run() {

                             System.out.println(Thread.currentThread().getId() + ",i:" + temp);

 

                       }

                  });

            }

總結:由於線程池大小爲3,每一個任務輸出index後sleep 2秒,因此每兩秒打印3個數字。

定長線程池的大小最好根據系統資源進行設置。如Runtime.getRuntime().availableProcessors()

newScheduledThreadPool

建立一個定長線程池,支持定時及週期性任務執行。延遲執行示例代碼以下:

ScheduledExecutorService newScheduledThreadPool = Executors.newScheduledThreadPool(5);

            for (int i = 0; i < 10; i++) {

                  final int temp = i;

                  newScheduledThreadPool.schedule(new Runnable() {

                       public void run() {

                             System.out.println("i:" + temp);

                       }

                  }, 3, TimeUnit.SECONDS);

}

表示延遲3秒執行。

 newSingleThreadExecutor

建立一個單線程化的線程池,它只會用惟一的工做線程來執行任務,保證全部任務按照指定順序(FIFO, LIFO, 優先級)執行。示例代碼以下:

    ExecutorService newSingleThreadExecutor = Executors.newSingleThreadExecutor();

         for (int i = 0; i < 10; i++) {

             final int index = i;

             newSingleThreadExecutor.execute(new Runnable() {

 

                  @Override

                  public void run() {

                      System.out.println("index:" + index);

                      try {

                          Thread.sleep(200);

                      } catch (Exception e) {

                          // TODO: handle exception

                      }

                  }

             });

         }

注意: 結果依次輸出,至關於順序執行各個任務。

線程池原理分析

相關文章
相關標籤/搜索