如何自定義線程池,以及注意事項


線程每次創建和關閉的開銷非常大,我們可以使用線程池來管理我們的線程,可以充分利用線程,減少不必要的開銷。

創建線程的方式有三種:

1、繼承Thread類

2、實現Runable或者Callable(帶返回值)接口

3、線程池的方式啟動

今天我們主要針對線程池來進行展開討論:

JDK自帶創建線程的方式有多種:

 

 

 這里是針對JDK1.8版本。每個創建都不一樣,但是使用JDK自帶的線程池會出現OOM問題,中小型公司一般狠難遇到,在阿里巴巴開發文檔上面有明確的標識:

 

 

 如果有需要此文檔,請點擊下面的url進行下載:https://www.cnblogs.com/han-1034683568/p/7680354.html

既然JDK自帶的線程池我們不能用,那么我們要自己手動來寫線程池了, 如果創建一個線程池:

下面的是對應的七個參數:

ThreadPoolExecutor(int corePoolSize,int maximumPoolSize,long keepAliveTime,TimeUnit unit,BlockingQueue<Runnable> workQueue,ThreadFactory threadFactory,RejectedExecutionHandler handler)

 我們可以這樣來創建線程池,其他里面的參數表示什么意思,我們在這里說明一下啊:

corePoolSize:線程中常駐核心線程數
maximumPoolSize:線程池能夠容納同時執行的最大線程數,此值必須大於1
keepAliveTime:多余空閑線程的存活時間,
unit:keepAliveTime的單位
workQueue:任務隊列,被提交但尚未被執行的任務
threadFactory:表示生成線程池中工作線程的線程工廠,用於創建線程,一般的默認即可
handler:拒絕策略,表示當隊列滿了,並且工作線程大於等於線程池的最大線程數(maximumPoolSize)
總體步驟:
1、在創建線程后,等待提交過來的任務請求
2、當調用execute()方法添加一個請求任務的時候,線程池會如何判斷
  2.1、如果正在運行的線程數小於
corePoolSize,那么馬上創建線程運行這個認為
  2.2、如果正在運行的線程數大於等於corePoolSize,那么將這個認為放入隊列
  2.3、如果這個時候隊列滿了,且小於maximumPoolSize,那么還是要創建線程立即執行任務
  2.4、如果隊列滿了,maximumPoolSize也滿了,將會啟動飽和拒絕策略來執行
3、將一個線程完成任務的時候,他會沖=從隊列里面取下一個任務來執行
4、當一個線程無事的時候,超過一定時間的時候,線程池會判斷:如果當前運行的線程數大於等於corePoolSize,那么這個線程將被停掉,所以線程池的所有任務完成后它最終收縮到corePoolSize的大小

線程池的拒絕策略:
ThreadPoolExecutor.AbortPolicy:丟棄任務並拋出RejectedExecutionException異常。(默認) ThreadPoolExecutor.DiscardPolicy:丟棄任務,但是不拋出異常。 ThreadPoolExecutor.DiscardOldestPolicy:丟棄隊列最前面的任務,然后重新提交被拒絕的任務 ThreadPoolExecutor.CallerRunsPolicy:由調用線程(提交任務的線程)處理該任務

添加阻塞隊列的方式有四種:

  1、add,添加不進去的時候,就會拋異常
  2、offer,添加進去返回true,添加不進去返回false
  3、put,會一直阻塞,直到可以放進去為止
  4、offer+時間,如果阻塞隊列滿的時候,往阻塞隊列添加,多久沒有添加進去,則停止添加

如何合理的配置線程池:
  這看你的業務了,看你的業務是CPU密集還是IO密集
  如果是CPU密集,一般配置的是CPU的核數或者核數+1
  如果是IO密集,大部分的線程都會阻塞,則需要多配置線程數,公式(CPU/(1-阻塞系數)),阻塞系數在0.8-0.9之間,比如8核CPU:8/(1-0.9) = 80個線程



 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM