自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

你能說下線程池有幾個(gè)參數(shù)嗎,分別代表什么?

開發(fā) 前端
task是worker對(duì)象封裝的任務(wù)。如果當(dāng)前worker對(duì)象上沒有任務(wù)就調(diào)用getTask去阻塞隊(duì)列拿任務(wù),如果能拿到就處理任務(wù)。如果getTask返回null就跳出循環(huán),進(jìn)入processWorkerExit方法。

關(guān)于線程池的問題,大多數(shù)面試官會(huì)問線程池的幾個(gè)參數(shù)的含義,今天就直接聊一聊線程池ThreadPoolExecutor。

先說下線程池中幾個(gè)參數(shù)的含義:

ThreadPoolExecutor初始化的時(shí)候一般會(huì)有7個(gè)參數(shù):

  • corePoolSize:核心線程數(shù)
  • maximumPoolSize:最大線程數(shù)
  • keepAliveTime:非核心線程?;顣r(shí)間
  • unit:?jiǎn)挝?/li>
  • workQueue:隊(duì)列
  • Executors.defaultThreadFactory():線程工場(chǎng)
  • 拒絕策略

ThreadPoolExecutor的工作原理:

往線程池中提交第一個(gè)任務(wù),底層會(huì)創(chuàng)建第一個(gè)核心線程,將線程和任務(wù)封裝為一個(gè)woker對(duì)象放入set集合中,接下來(lái)每提交一個(gè)的任務(wù)都會(huì)對(duì)應(yīng)創(chuàng)建一個(gè)核心線程和這個(gè)任務(wù)封裝的woker對(duì)象放入set集合中,直到核心線程數(shù)達(dá)到corePoolSize,再次提交到線程池的任務(wù)會(huì)被放到阻塞隊(duì)列排隊(duì)執(zhí)行,如果放隊(duì)列的過程中,隊(duì)列滿了,就會(huì)創(chuàng)建一個(gè)非核心線程和這個(gè)任務(wù)封裝為woker對(duì)象放入set集合中,如果最終已經(jīng)達(dá)到最大線程數(shù)maximumPoolSize,就采用拒絕策略。如果放入隊(duì)列過程中發(fā)現(xiàn)工作線程數(shù)位0,則創(chuàng)建一個(gè)空任務(wù)的Worker。

再來(lái)看下線程池的標(biāo)識(shí):

線程池的標(biāo)識(shí)有兩層含義:

  • 一個(gè)含義是當(dāng)前線程池中的線程數(shù)量;
  • 一個(gè)含義是當(dāng)前線程池的狀態(tài);

底層是用按位分隔的設(shè)計(jì)方式將一個(gè)int類型的變量的32位進(jìn)行分割,用高3位表示線程狀態(tài),低29位表示線程數(shù)量。

線程池的5個(gè)狀態(tài):RUNNING= -1,正常運(yùn)行狀態(tài) SHUTDOWN= 0, 表示不接受新任務(wù),只把隊(duì)列中的任務(wù)處理完結(jié)束。STOP= 1,表示不接受新任務(wù),也不處理隊(duì)列中的任務(wù)了。IDYING= 2,非正常狀態(tài) TERMINATED = 3,死亡狀態(tài)

按位分割的好處就是用一個(gè)變量表示兩個(gè)狀態(tài),在修改的時(shí)候可以利用cas保證原子性。

Worker對(duì)象創(chuàng)建邏輯是由addWorker方法實(shí)現(xiàn)的。

addWorker方法邏輯:

1.retry;雙層循環(huán)

第一層循環(huán)主要判斷:如果當(dāng)前線程池狀態(tài)為RUNNING就放行, 如果狀態(tài)為SHUTDOWN就必須滿足傳進(jìn)來(lái)的新任務(wù)為null,隊(duì)列中有待處理的任務(wù)才會(huì)放行(因?yàn)镾HUTDOWN狀態(tài)下不接受新任務(wù),只處理隊(duì)列中的任務(wù));如果狀態(tài)為STOP,IDYING,TERMINATED就一定不放行;

第二層循環(huán)主要是判斷線程數(shù),如果是創(chuàng)建核心線程,就判斷是否達(dá)到corePoolSize,否則就判斷是否達(dá)到maximumPoolSize,如果達(dá)到就返回fasle不放行。

如果未達(dá)到就放行,放行的時(shí)候會(huì)利用cas更新線程數(shù),如果更新成功則兩層循環(huán)結(jié)束,繼續(xù)下面的邏輯。

因?yàn)槭莄as操作,多線程的情況下可能會(huì)有更新線程數(shù)量失敗的情況,在這種情況下要判斷之前獲取的線程池狀態(tài)和現(xiàn)在的線程池狀態(tài)是否一致,如果不一致那就要重新判斷狀態(tài),從而進(jìn)入到外層循環(huán)的下一輪循環(huán),如果一致就只需要進(jìn)入到內(nèi)層循環(huán)的下一輪循環(huán)。

2.創(chuàng)建Worker對(duì)象

接下來(lái)就是創(chuàng)建Worker(任務(wù)),Worker類繼承aqs,封裝了線程工廠,初始化的時(shí)候會(huì)利用工廠創(chuàng)建一個(gè)線程,并且和傳進(jìn)來(lái)的任務(wù)封裝為worker對(duì)象。

獲取線程池全局鎖(reentrylock作為線程池全局鎖),進(jìn)行上鎖操作

將創(chuàng)建的worker加入workers集合,workers是一個(gè)hashset集合。

放入集合后就可以解鎖了

worker創(chuàng)建完成了,接下來(lái)就是啟動(dòng)線程,啟動(dòng)線程后就會(huì)執(zhí)行worker中的run方法

3.run方法流程

這個(gè)方法中主要的邏輯是這段代碼

while (task != null || (task = getTask()) != null){
  邏輯
}

task是worker對(duì)象封裝的任務(wù)。如果當(dāng)前worker對(duì)象上沒有任務(wù)就調(diào)用getTask去阻塞隊(duì)列拿任務(wù),如果能拿到就處理任務(wù)。如果getTask返回null就跳出循環(huán),進(jìn)入processWorkerExit方法。

我們知道線程池中的任務(wù)是放在隊(duì)列中的,ThreadPoolExecutor中的隊(duì)列一般默認(rèn)是阻塞隊(duì)列LinkedBlockingQueue,

getTask()方法會(huì)在這個(gè)隊(duì)列中拿任務(wù),如果有任務(wù)就直接返回任務(wù),如果此時(shí)隊(duì)列中無(wú)任務(wù),當(dāng)前線程會(huì)阻塞等待任務(wù)到來(lái)。

但是如果設(shè)置了非核心線程最大空閑時(shí)間keepAliveTime,代表非核心線程的worker對(duì)象中的線程在拿任務(wù)的時(shí)候不會(huì)用take方法,而是用poll,poll這個(gè)方法可以設(shè)置阻塞等待時(shí)間為keepAliveTime。當(dāng)超過這個(gè)時(shí)間還沒有任務(wù)就會(huì)返回null。

4.processWorkerExit方法邏輯

上一步中如果沒有獲取到任務(wù)并且返回了null就會(huì)進(jìn)入processWorkerExit方法。這個(gè)方法的邏輯就是把當(dāng)前非核心線程的worker從workers集合中移除。最后會(huì)做一個(gè)判斷:如果此時(shí)沒有任何工作線程了,并且阻塞隊(duì)列中還有任務(wù),那就再創(chuàng)建一個(gè)不帶任務(wù)的非核心線程worker。保證有線程去處理隊(duì)列中的任務(wù)。

拒絕策略:

  • AbortPolicy(默認(rèn)):丟棄任務(wù)并拋出 RejectedExecutionException 異常。
  • CallerRunsPolicy:由調(diào)用線程處理該任務(wù)。
  • DiscardPolicy:丟棄任務(wù),但是不拋出異常??梢耘浜线@種模式進(jìn)行自定義的處理方式。
  • DiscardOldestPolicy:丟棄隊(duì)列最早的未處理任務(wù),然后重新嘗試執(zhí)行任務(wù)。

其他了解:

線程監(jiān)控API:
 while (true) {
 System.out.println();
 int queueSize = tpe.getQueue().size();
 System.out.println("當(dāng)前排隊(duì)線程數(shù):" + queueSize);
 int activeCount = tpe.getActiveCount();
 System.out.println("當(dāng)前活動(dòng)線程數(shù):" + activeCount);
 long completedTaskCount = tpe.getCompletedTaskCount();
 System.out.println("執(zhí)行完成線程數(shù):" + completedTaskCount);
 long taskCount = tpe.getTaskCount();
 System.out.println("總線程數(shù):" + taskCount);
 Thread.sleep(3000);
 }


責(zé)任編輯:武曉燕 來(lái)源: 碼農(nóng)本農(nóng)
相關(guān)推薦

2023-05-05 09:04:41

文本數(shù)據(jù)ChatGPT

2023-11-29 16:38:12

線程池阻塞隊(duì)列開發(fā)

2023-10-27 15:31:04

For循環(huán)Foreach循環(huán)

2024-07-15 08:20:24

2023-12-13 13:31:00

useEffect對(duì)象瀏覽器

2023-10-18 08:04:15

taskworker任務(wù)

2023-11-28 08:20:25

2021-02-01 08:28:24

Linux線程池Linux系統(tǒng)

2023-06-08 07:48:03

Java線程池

2019-12-30 09:28:53

Kafka集群ZooKeeper

2022-03-09 07:35:24

線程池線程參數(shù)

2023-01-29 08:04:24

線程池非核心線程任務(wù)

2025-01-03 08:40:53

Java并發(fā)編程Guava庫(kù)

2021-06-01 10:49:22

線程池Java開發(fā)

2021-06-03 14:23:57

線程線程池JAVA

2024-11-11 00:00:01

線程池工具

2023-01-07 17:41:36

線程池并發(fā)

2024-10-10 16:53:53

守護(hù)線程編程

2020-09-03 06:42:12

線程安全CPU

2021-01-06 17:28:00

MySQL數(shù)據(jù)庫(kù)緩存池
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號(hào)