您好,登錄后才能下訂單哦!
這篇文章主要介紹“線程的相關知識點總結”,在日常操作中,相信很多人在線程的相關知識點總結問題上存在疑惑,小編查閱了各式資料,整理出簡單好用的操作方法,希望對大家解答”線程的相關知識點總結”的疑惑有所幫助!接下來,請跟著小編一起來學習吧!
先說阻塞隊列,即生產者消費者模式
舉個列子
在多線程下:所謂阻塞,在某些情況下會掛起線程(即阻塞),一旦條件滿足,被掛起的線程又會自動被喚醒。
為什么需要BlockingQueue?
好處是我們不需要關心什么時候需要阻塞線程,什么時候需要喚醒線程,因為這一切BlockingQueue都給你辦了。在concurrent包發布以前,在多線程環境下,我們每個程序員都必須去自己控制這些細節,尤其還要兼顧效率和線程安全,而這會給我們的程序帶來不小的復雜度。
線程池的底層就是阻塞隊列:
ArrayBlockingQueue:由數組結構組成的有界阻塞隊列。
LinkedBlockingQueue:由鏈表結構組成的有界(默認值為Integer.MAX_VALUE)阻塞隊列。
PriorityBlockingQueue:支持優先級排序的無界塞隊列。
DelayQueue:使用優先級隊列實現的延遲無界阻塞隊列。
SynchronousQueue:不存儲元素的阻塞隊列,也即單個元素的隊列。
LinkedTransferQueue:由鏈表結構組成的無界阻塞隊列。
LinkedBlockingDeque:由鏈表結構組成的雙向阻塞隊列
說一下SynchronousQueue,與其他BlockingQueue不同,SynchronousQueue是一個不存儲元素的BlockingQueue(沒有容量)。
每一個put操作必須要等待一個take操作,否則不能繼續添加元素,反之亦然。
創建線程的幾種方式
1.繼承Thread類
2.實現Runable接口
3.實現Callable接口
Callable FutureTask實現了Runable接口,構造方法傳入Callable(適配器模式)。面向接口的編程。
4.線程池…..
ThreadPoolExecutor + 阻塞隊列
1、newCachedThreadPool:用來創建一個可以無限擴大的線程池,適用于負載較輕的場景,執行短期異步任務。(可以使得任務快速得到執行,因為任務時間執行短,可以很快結束,也不會造成cpu過度切換)
2、newFixedThreadPool:創建一個固定大小的線程池,因為采用無界的阻塞隊列,所以實際線程數量永遠不會變化,適用于負載較重的場景,對當前線程數量進行限制。(保證線程數可控,不會造成線程過多,導致系統負載更為嚴重)
3、newSingleThreadExecutor:創建一個單線程的線程池,適用于需要保證順序執行各個任務。
4、newScheduledThreadPool:適用于執行延時或者周期性任務。
核心參數
1.corePoolSize:線程池中的常駐核心線程數
2.maximumPooISize:線程池能夠容納同時執行的最大線程數,此值必須大于等于1
3.keepAliveTime:多余的空閑線程的存活時間。當前線程池數量超過corepooISize時,當空閑時間達到keepAeTime值時,多余空閑線程會被銷毀直到只剩下corepooISize個線程為止
4.unit:keepAliveTime的單位
5.workQueue:任務隊列,被提交但尚未被執行的任務
6.threadFactory:表示生成線程池中工作線程的線程工廠,用于創建線程一般用默認的即可
7.handIer:拒絕策略,表示當隊列滿了并且工作線程大于等于線程池的最大線程數(maximumPooISize)底層原理
1. 在創建了線程池后,等待提交過來的任務請求。
2. 當調用execute()方法添加一個請求任務時,線程池會做如下判斷:
2.1如果正在運行的線程數量小于corePoolSize,那么直接創建線程運行這個任務;
2.2如果正在運行的線程數量大于或等于corePoolSize,那么將這個任務放入隊列;
2.3如果這時候隊列滿了且正在運行的線程數量還小于maximumPoolSze,那么還是要創建非核心線程立刻運行這個任務;
2.4如果隊列滿了且正在運行的線程數量大于或等于maximumPoolSze,那么線程池會啟動飽和拒絕略來執行。
3. 當一個線程完成任務時,它會從隊列中取下一個任務來執行。
4. 當一個線程無事可做超過一定的時間(keepAliveTime)時,線程池會判斷:|
如果當前運行的線程數大于corePoolSize,那么這個線程就被停掉。所以線程池的所有任務完成后它最終會收縮到corePoolStze的大小。拒絕策略
AbortPolicy(默認):直拋出RejectedExecutionExcepton異常阻止系統正常運行。
CallerRunsPolicy:“調用者運行”一種調節機制,該策略既不會拋棄任務,也不會拋出異常,而是將某些任務回退給調用者運行。
DiscardOldestPolicy:拋棄隊列中等待最久的任務,然后把當前任務加入隊中嘗試再次提交當前任務。
DiscardPolicy:直接丟棄任務,不予任何處理也不拋出異常。如果允許任務丟失,這是最好的一種方案。
擴展:合理配置線程,你是如何考慮的?
1.cpu密集型
CPU密集的意思是該任務需要大量的運算,而沒有阻塞,CPU一直全速運行。
CPU密集任務只有在真正的多核CPU上才可能得到加速(通過多線程),而在單核CPU上,無論你開幾個模擬的多線程該任務都不可能得到加速,因為CPU總的運算能力就那些。
因為CPU密集型任務使得CPU使用率很高,若開過多的線程數,會造成CPU過度切換,所以CPU密集型任務配置盡可能少的線程數量:
一般公式:CPU核數+1個線程的線程池2.io密集型
可以使用稍大的線程池,一般為2*CPU核心數。 IO密集型任務CPU使用率并不高,因此可以讓CPU在等待IO的時候有其他線程去處理別的任務,充分利用CPU時間。
故需要多配置線程數:
參公式:CPU核數/1-阻塞系數 阻塞系數在0.8~0.9之間
比如8核CPU:8/1-0.9=80個線程數
線程池為什么要使用阻塞隊列?
1.因為線程若是無限制的創建,可能會導致內存占用過多而產生OOM,并且會造成cpu過度切換。
2.阻塞隊列可以保證任務隊列中沒有任務時阻塞獲取任務的線程,使得線程進入wait狀態,釋放cpu資源。當隊列中有任務時才喚醒對應線程從隊列中取出消息進行執行。使得在線程不至于一直占用cpu資源。
到此,關于“線程的相關知識點總結”的學習就結束了,希望能夠解決大家的疑惑。理論與實踐的搭配能更好的幫助大家學習,快去試試吧!若想繼續學習更多相關知識,請繼續關注億速云網站,小編會繼續努力為大家帶來更多實用的文章!
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。