日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

多线程:线程池

發布時間:2025/3/21 编程问答 25 豆豆
生活随笔 收集整理的這篇文章主要介紹了 多线程:线程池 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

深入淺出線程池

jdk1.5引入Executor線程池框架,通過它把任務的提交和執行進行解耦,只需要定義好任務,然后提交給線程池,而不用關心該任務是如何執行、被哪個線程執行,以及什么時候執行。
初始化線程池(4種)
簡介:
Java線程池的工廠類:Executors類,

初始化4種類型的線程池:

newFixedThreadPool()
說明:初始化一個指定線程數的線程池,其中corePoolSize== maxiPoolSize,使用LinkedBlockingQuene作為阻塞隊列
特點:即使當線程池沒有可執行任務時,也不會釋放線程。
newCachedThreadPool()
說明:初始化一個可以緩存線程的線程池,默認緩存60s,線程池的線程數可達到Integer.MAX_VALUE,即2147483647,內部使用SynchronousQueue作為阻塞隊列;
特點:在沒有任務執行時,當線程的空閑時間超過keepAliveTime,會自動釋放線程資源;當提交新任務時,如果沒有空閑線程,則創建新線程執行任務,會導致一定的系統開銷
因此,使用時要注意控制并發的任務數,防止因創建大量的線程導致而降低性能。
newSingleThreadExecutor()
說明:初始化只有一個線程的線程池,內部使用LinkedBlockingQueue作為阻塞隊列。
特點:如果該線程異常結束,會重新創建一個新的線程繼續執行任務,唯一的線程可以保證所提交任務的順序執行
newScheduledThreadPool()
特點:初始化的線程池可以在指定的時間內周期性的執行所提交的任務,在實際的業務場景中可以使用該線程池定期的同步數據。


1.CacheThreadPool?
這是一個線程數變動性非常強的線程池,默認配置下,它可以開啟無限多個線程(Integer.maxSize 和 JVM允許線程數范圍內)。且如果該線程池里的線程在60秒內如果是處于空閑狀態(即沒任務執行),那么該線程就會被回收,不再由線程池維護。如果有新任務進來時,由于之前的線程池里的線程已被回收,那么新的線程也會再次創建。當執行完任務,60秒內依舊無新任務的可執行話,那么該線程又會被再次回收。?

綜合該線程池的特性,我們可以思考下什么情況下應該使用這類線程池。比如:我們的應用服務器上面,會在非固定時間(時間跨域度會盡可能大)和非固定的任務數量。?


2.FixedThreadPool
FixedThreadPool一個固定數量的線程池,且該線程池不會隨著任務的變化而增多或減少線程數量。即該線程池下的線程池如果你不主動調用銷毀shutdowm、purge之類的方法。那么這些線程將會永遠被線程池維護著。

3.SingleThreadExecutor
SingleThreadExecutor是一個固定單線程的線程池,該線程池會永遠都保持著一個線程的活動狀態,如果該線程池的單線程因某些異常而退出后,線程池會繼續創建一個新的線程。

4.ScheduledThreadPool
ScheduledThreadPool是一個支持任務定時調度的線程池。


總結:除了newScheduledThreadPool的內部實現特殊一點之外,其它線程池內部都是基于ThreadPoolExecutor類(Executor的子類)實現的。

ThreadPoolExecutor內部具體實現:
ThreadPoolExecutor類構造器語法形式:

ThreadPoolExecutor(corePoolSize,maxiPoolSize,keepAliveTime,timeUnit,workQueue,threadFactory,handle);??

方法參數:
? ? ?corePoolSize:核心線程數
? ? ?maxPoolSize:最大線程數
?????keepAliveTime:線程存活時間(在corePore<*<maxPoolSize情況下有用)
?????timeUnit:存活時間的時間單位
?????workQueue:阻塞隊列(用來保存等待被執行的任務

注:關于workQueue參數的取值,JDK提供了4種阻塞隊列類型供選擇:
?????ArrayBlockingQueue:基于數組結構的有界阻塞隊列,按FIFO排序任務;
? ? ?LinkedBlockingQueue:基于鏈表結構的阻塞隊列,按FIFO排序任務,有界有上限,所生成的BlockingQueue的大小由Integer.MAX_VALUE來決定。

????SynchronousQueue:一個不存儲元素的阻塞隊列,每個插入操作必須等到另一個線程調用移除操作,否則插入操作一直處于阻塞狀態,吞吐量通常要高于ArrayBlockingQueue;

?????PriorityBlockingQueue:具有優先級的無界阻塞隊列;

?????threadFactory:線程工廠,主要用來創建線程;

?????handler:表示當拒絕處理任務時的策略,有以下四種取值

?注:?當線程池的飽和策略,當阻塞隊列滿了,且沒有空閑的工作線程,如果繼續提交任務,必須采取一種策略處理該任務,線程池提供了4種策略:

ThreadPoolExecutor.AbortPolicy:丟棄任務并拋出RejectedExecutionException異常。? 默認策略

ThreadPoolExecutor.DiscardPolicy:也是丟棄任務,但是不拋出異常。

ThreadPoolExecutor.DiscardOldestPolicy:丟棄隊列最前面的任務,然后重新嘗試執行任務(重復此過程)

ThreadPoolExecutor.CallerRunsPolicy:由調用線程處理該任務。用于被拒絕任務的處理程序,它直接在?execute?方法的調用線程中運行被拒絕的任務;如果執行程序已關閉,則會丟棄該任務。

RejectedExecutionHandler?handler?=? new?ThreadPoolExecutor.CallerRunsPolicy();

當然也可以根據應用場景實現RejectedExecutionHandler接口,自定義飽和策略,如記錄日志或持久化存儲不能處理的任務。

?線程池的狀態(5種)
其中AtomicInteger變量ctl的功能非常強大:利用低29位表示線程池中線程數,通過高3位表示線程池的運行狀態:
1、RUNNING:-1 << COUNT_BITS,即高3位為111,該狀態的線程池會接收新任務,并處理阻塞隊列中的任務;
2、SHUTDOWN:?0 << COUNT_BITS,即高3位為000,該狀態的線程池不會接收新任務,但會處理阻塞隊列中的任務;
3、STOP?:?1<< COUNT_BITS,即高3位為001,該狀態的線程不會接收新任務,也不會處理阻塞隊列中的任務,而且會中斷正在運行的任務;
4、TIDYING?:?2<< COUNT_BITS,即高3位為010,該狀態表示線程池對線程進行整理優化;
5、TERMINATED:?3 << COUNT_BITS,即高3位為011,該狀態表示線程池停止工作;

?向線程池提交任務(2種)


有兩種方式:

? ???Executor.execute(Runnablecommand);

?????ExecutorService.submit(Callable<T> task);

execute()內部實現


1.首次通過workCountof()獲知當前線程池中的線程數,

??如果小于corePoolSize, 就通過addWorker()創建線程并執行該任務;

 否則,將該任務放入阻塞隊列;

2. 如果能成功將任務放入阻塞隊列中, ?

如果當前線程池是非RUNNING狀態,則將該任務從阻塞隊列中移除,然后執行reject()處理該任務;

如果當前線程池處于RUNNING狀態,則需要再次檢查線程池(因為可能在上次檢查后,有線程資源被釋放),是否有空閑的線程;如果有則執行該任務;

3、如果不能將任務放入阻塞隊列中,說明阻塞隊列已滿;那么將通過addWoker()嘗試創建一個新的線程去執行這個任務;如果addWoker()執行失敗,說明線程池中線程數達到maxPoolSize,則執行reject()處理任務;

?sumbit()內部實現


會將提交的Callable任務會被封裝成了一個FutureTask對象

FutureTask類實現了Runnable接口,這樣就可以通過Executor.execute()提交FutureTask到線程池中等待被執行,最終執行的是FutureTask的run方法;?

比較:

?兩個方法都可以向線程池提交任務,execute()方法的返回類型是void,它定義在Executor接口中, 而submit()方法可以返回持有計算結果的Future對象,它定義在ExecutorService接口中,它擴展了Executor接口,其它線程池類像ThreadPoolExecutorScheduledThreadPoolExecutor都有這些方法。?

線程池的關閉(2種)

ThreadPoolExecutor提供了兩個方法,用于線程池的關閉,分別是shutdown()和shutdownNow(),其中:

shutdown():不會立即終止線程池,而是要等所有任務緩存隊列中的任務都執行完后才終止,但再也不會接受新的任務

shutdownNow():立即終止線程池,并嘗試打斷正在執行的任務,并且清空任務緩存隊列,返回尚未執行的任務

?線程池容量的動態調整
ThreadPoolExecutor提供了動態調整線程池容量大小的方法:setCorePoolSize()和setMaximumPoolSize(),

總結:
線程池中的核心線程數,當提交一個任務時,線程池創建一個新線程執行任務,直到當前線程數等于corePoolSize;如果當前線程數為corePoolSize,繼續提交的任務被保存到阻塞隊列中,等待被執行;如果阻塞隊列滿了,那就創建新的線程執行當前任務;直到線程池中的線程數達到maxPoolSize,這時再有任務來,只能執行reject()處理該任務;

注:如果執行了線程池的prestartAllCoreThreads()方法,線程池會提前創建并啟動所有核心線程。


?

總結

以上是生活随笔為你收集整理的多线程:线程池的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。