天天看點

線程池

  關于線程池的源碼分析,在這裡也沒認真說明,後面單獨起一片文章進行研究。

1.大綱

  線程池介紹

  建立與停止線程池

  常見的線程池特點與用法

  任務太多,怎麼拒絕

  鈎子方法

  實作原理,源碼分析

  使用線程池的主要點

一:介紹

1.重要性

  使用中重要

  面試中重要

2.池

  線程可以複用

  可以控制資源的總量

3.不使用線程池些的程式

  這裡有兩個程式,隻粘貼進行循環對每個任務進行建立線程,并執行

  

4.為什麼使用線程池

  反複的建立,開銷大

    讓一部分的線程保持工作,反複的執行任務

  過多的線程會占用太多的記憶體

    使用少量的線程

5.線程池的好處

  加快響應速度

  更好的利用CPU,與記憶體。選擇合适的線程數

  統一管理

6.使用場景

  伺服器接收大量的請求

  多個線程的建立

二:建立與停止線程池

1.線程池的構造函數的參數

  corePoolSize:核心線程數,int

  maxPoolSize:最大的線程數,int

  keepAliveTime:存活時間,long

  workQueue:任務存儲隊列,BlockingQueue

  threadFactory:工廠類,ThreadFactory

  Handler:拒絕政策,RejectedExecutionHandler

2.corePoolSize

  線程池進行初始化的時候,線程池裡沒有任何的線程,線程池會等待有任務到來的時候,再進行建立新線程執行任務

3.macPoolSize

  線程池有可能子啊核心線程數的基礎上,額外增加一些線程,但是這些新增加的線程數有一定的上限,這個就是最大量

  如果超過了corePoolSize的時候,先将任務放到隊列中。

  隊列中滿了,才會去看

4.添加線程的規則

  如果線程小于corePoolSize的時候,即使線程有處于空閑狀态,也會繼續建立新的線程運作新的任務

  如果等于大于corePoolSize,但是小于maxPoolSize,放入隊列

  如果隊列已滿,并且線程小于maxPoolSize,建立新的線程

線程池

5.keepAliveTime

  主要看是控制的是誰。

  如果線程池的目前的線程數多于了corePoolSize,那麼多于的線程空閑時間超過keepAliveTime,将會被終止

  減少資源消耗

6.ThreadFactory

  新的線程預設使用Exectors.defaultThreadFactory(),建立的線程都在一個線程組,擁有相同的NORM_PRIORITY優先級,并且都不是守護線程

7.workQueue

  工作隊列

  最常見的隊列類型:

    直接交換:SynchronousQueue,内部沒有容量

    無界隊列:LinkedBlockingQueue

    有界隊列:ArrayBlockingQueue

三:常見的線程池

1.FixedThreadPool建立

  可以看見,corePoolSize與maxPoolSize是相等的

  然後使用的是無界隊列。

  由于傳遞進去的任務是沒有容量上限的,可能占用大量的記憶體,出現OOM

2.示範溢出

  效果:

3.SingleThreadExector的使用

  說明:

  相比于FixedThreadPool,隻是corePoolSize與macPoolSize都是1,其他不變

4.也會出現OOM

5.CachedThreadPool

  可緩存線程池,無界的線程池,可以自動回收多于線程的功能

  其中,最大的線程數沒有限制,也是一個大的弊端。如果任務量過大,一樣會出現的是OOM

6.測試

  建立了很多的線程

7.ScheduledThreadPool

  支援定時與周期性的執行的線程池

  核心線程是傳遞過去的,但是最大的核心線程數是INTEGER.MAX_VALUE

8.延遲一定時間之後運作

  定時

9.周期性的運作

  周期

10.總結

線程池

   主要注意的是CacheDThreadPool與ScheduleThreadPool的對比。

  CachedThreadPool為啥使用SynchronousQueue,因為有任務不需要進行存儲,直接交給線程執行就行了。

  ScheduledThreadPool使用的是延遲隊列DelayedWorkQueue

 

四:線程池中的線程數量設定

1.計算密集型的

  為cpu核心數的1~2倍

2.耗時IO型的

  最佳線程數一般大于cpu很多倍。

  以jvm線程監控顯示繁忙情況為依據,參考brain goetz推薦的計算方法

3.計算方法

  cpu核心數 * (1+平均等待時間/平均工作時間)

五:停止線程池

1.shutdown

  要線程中,會隊列中的線程任務都執行完成後,再進行停止

  對拒絕新的任務

2.測試

  可以發現,在執行一段時間後,就可以發現,真的不再進行接收任務了

3.isShutdown

  可以知道線程被停止過了

   先false,然後true

4.isTerminated

  傳回是否真正的結束

    效果:

 5.awaitTermination

  所有的任務都執行完畢,等待的時間到了,等待過程中被打斷都會傳回,否則阻塞。

  說明:8秒内,如果關閉了線程,并且都執行完成傳回true,否則是false

 6.shutdownNow

  立刻關閉線程

  存在傳回未執行的任務。

六:拒絕政策

 1.拒絕時機

  Executor關閉時

  最大線程和隊列已滿

2.拒絕政策

  AbsortPolicy:直接抛出異常

  DiscradPolicy:默默丢棄

  DiscardOldestPolicy:丢棄最老的任務

  CallerRunsPolicy:誰送出的任務,則有誰進行運作,這樣可以降低送出速度

七:鈎子方法

1.說明

  在任務的前後

  日志,統計

2.暫停線程池

八:源碼

1.組成部分

  線程池管理器

  工作線程

  任務隊列

  任務接口

2.Exector家族

線程池

3.Exector

  頂層接口,隻有一個方法

4.ExecuorService

  繼承了Excetor,然後增加了幾個新的方法

  初步的有了管理線程池的方法

線程池

5.Excetors  

  這是一個工具類

  進入可以發現是使用ThreadPoolExector進行建立的線程

6.線程池實作任務複用的原理

  execute:

線程池

  添加到worker

線程池
線程池

  進行運作:

線程池

九:線程池狀态

1.線程池狀态

  Running:接收新任務并處理排隊任務

  SHUTDOWN:不接受新任務,但是處理排隊任務

  stop:不接受新任務,也不處理排隊任務,并中斷正在進行的任務

  tidying:所有的任務都已經終結,workerCount為零時,線程就會轉為這個狀态,并且運作terminate()方法

  TERMIMATED:運作完成

2.狀态值

   

線程池