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

歡迎訪問(wèn) 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) > 编程语言 > java >内容正文

java

Java面试——线程池

發(fā)布時(shí)間:2023/12/18 java 46 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Java面试——线程池 小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

1、類比介紹

  假如有一個(gè)工廠,工廠里面有10個(gè)工人,每個(gè)工人同時(shí)只能做一件任務(wù)。

  因此只要當(dāng)10個(gè)工人中有工人是空閑的,來(lái)了任務(wù)就分配給空閑的工人做;

  當(dāng)10個(gè)工人都有任務(wù)在做時(shí),如果還來(lái)了任務(wù),就把任務(wù)進(jìn)行排隊(duì)等待;

  如果說(shuō)新任務(wù)數(shù)目增長(zhǎng)的速度遠(yuǎn)遠(yuǎn)大于工人做任務(wù)的速度,那么此時(shí)工廠主管可能會(huì)想補(bǔ)救措施,比如重新招4個(gè)臨時(shí)工人進(jìn)來(lái);

  然后就將任務(wù)也分配給這4個(gè)臨時(shí)工人做;

  如果說(shuō)著14個(gè)工人做任務(wù)的速度還是不夠,此時(shí)工廠主管可能就要考慮不再接收新的任務(wù)或者拋棄前面的一些任務(wù)了。

  當(dāng)這14個(gè)工人當(dāng)中有人空閑時(shí),而新任務(wù)增長(zhǎng)的速度又比較緩慢,工廠主管可能就考慮辭掉4個(gè)臨時(shí)工了,只保持原來(lái)的10個(gè)工人,畢竟請(qǐng)額外的工人是要花錢的。

?

  這個(gè)例子中的corePoolSize就是10,而maximumPoolSize就是14(10+4)。

  也就是說(shuō)corePoolSize就是線程池大小,maximumPoolSize在我看來(lái)是線程池的一種補(bǔ)救措施,即任務(wù)量突然過(guò)大時(shí)的一種補(bǔ)救措施。

2、源碼分析

在ThreadPoolExecutor類中,最核心的任務(wù)提交方法是execute()方法,雖然通過(guò)submit也可以提交任務(wù),但是實(shí)際上submit方法里面最終調(diào)用的還是execute()方法,所以我們只需要研究execute()方法的實(shí)現(xiàn)原理即可:

public void execute(Runnable command) {if (command == null)throw new NullPointerException();if (poolSize >= corePoolSize || !addIfUnderCorePoolSize(command)) {if (runState == RUNNING && workQueue.offer(command)) {if (runState != RUNNING || poolSize == 0)ensureQueuedTaskHandled(command);}else if (!addIfUnderMaximumPoolSize(command))reject(command); // is shutdown or saturated } }

?

在addThread方法中,首先用提交的任務(wù)創(chuàng)建了一個(gè)Worker對(duì)象,然后調(diào)用線程工廠threadFactory創(chuàng)建了一個(gè)新的線程t,然后將線程t的引用賦值給了Worker對(duì)象的成員變量thread,接著通過(guò)workers.add(w)將Worker對(duì)象添加到工作集當(dāng)中。

private Thread addThread(Runnable firstTask) {Worker w = new Worker(firstTask);Thread t = threadFactory.newThread(w); //創(chuàng)建一個(gè)線程,執(zhí)行任務(wù) if (t != null) {w.thread = t; //將創(chuàng)建的線程的引用賦值為w的成員變量 workers.add(w);int nt = ++poolSize; //當(dāng)前線程數(shù)加1 if (nt > largestPoolSize)largestPoolSize = nt;}return t; }

?

下面總結(jié)一下:

  1)首先,要清楚corePoolSize和maximumPoolSize的含義;

  2)其次,要知道Worker是用來(lái)起到什么作用的;

  3)要知道任務(wù)提交給線程池之后的處理策略,這里總結(jié)一下主要有4點(diǎn):

  • 如果當(dāng)前線程池中的線程數(shù)目小于corePoolSize,則每來(lái)一個(gè)任務(wù),就會(huì)創(chuàng)建一個(gè)線程去執(zhí)行這個(gè)任務(wù);
  • 如果當(dāng)前線程池中的線程數(shù)目>=corePoolSize,則每來(lái)一個(gè)任務(wù),會(huì)嘗試將其添加到任務(wù)緩存隊(duì)列當(dāng)中,若添加成功,則該任務(wù)會(huì)等待空閑線程將其取出去執(zhí)行;若添加失敗(一般來(lái)說(shuō)是任務(wù)緩存隊(duì)列已滿),則會(huì)嘗試創(chuàng)建新的線程去執(zhí)行這個(gè)任務(wù);
  • 如果當(dāng)前線程池中的線程數(shù)目達(dá)到maximumPoolSize,則會(huì)采取任務(wù)拒絕策略進(jìn)行處理;
  • 如果線程池中的線程數(shù)量大于 corePoolSize時(shí),如果某線程空閑時(shí)間超過(guò)keepAliveTime,線程將被終止,直至線程池中的線程數(shù)目不大于corePoolSize;如果允許為核心池中的線程設(shè)置存活時(shí)間,那么核心池中的線程空閑時(shí)間超過(guò)keepAliveTime,線程也會(huì)被終止。

3.線程池中的線程初始化

  默認(rèn)情況下,創(chuàng)建線程池之后,線程池中是沒(méi)有線程的,需要提交任務(wù)之后才會(huì)創(chuàng)建線程。

  在實(shí)際中如果需要線程池創(chuàng)建之后立即創(chuàng)建線程,可以通過(guò)以下兩個(gè)方法辦到:

  • prestartCoreThread():初始化一個(gè)核心線程;
  • prestartAllCoreThreads():初始化所有核心線程

?

4.任務(wù)緩存隊(duì)列及排隊(duì)策略

  在前面我們多次提到了任務(wù)緩存隊(duì)列,即workQueue,它用來(lái)存放等待執(zhí)行的任務(wù)。

  workQueue的類型為BlockingQueue<Runnable>,通??梢匀∠旅嫒N類型:

  1)ArrayBlockingQueue:基于數(shù)組的先進(jìn)先出隊(duì)列,此隊(duì)列創(chuàng)建時(shí)必須指定大小;

  2)LinkedBlockingQueue:基于鏈表的先進(jìn)先出隊(duì)列,如果創(chuàng)建時(shí)沒(méi)有指定此隊(duì)列大小,則默認(rèn)為Integer.MAX_VALUE;

  3)synchronousQueue:這個(gè)隊(duì)列比較特殊,它不會(huì)保存提交的任務(wù),而是將直接新建一個(gè)線程來(lái)執(zhí)行新來(lái)的任務(wù)。

?

5.任務(wù)拒絕策略

當(dāng)線程池的任務(wù)緩存隊(duì)列已滿并且線程池中的線程數(shù)目達(dá)到maximumPoolSize,如果還有任務(wù)到來(lái)就會(huì)采取任務(wù)拒絕策略,通常有以下四種策略:

ThreadPoolExecutor.AbortPolicy:丟棄任務(wù)并拋出RejectedExecutionException異常。 ThreadPoolExecutor.DiscardPolicy:也是丟棄任務(wù),但是不拋出異常。 ThreadPoolExecutor.DiscardOldestPolicy:丟棄隊(duì)列最前面的任務(wù),然后重新嘗試執(zhí)行任務(wù)(重復(fù)此過(guò)程) ThreadPoolExecutor.CallerRunsPolicy:由調(diào)用線程處理該任務(wù)

6.線程池的關(guān)閉

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

  • shutdown():不會(huì)立即終止線程池,而是要等所有任務(wù)緩存隊(duì)列中的任務(wù)都執(zhí)行完后才終止,但再也不會(huì)接受新的任務(wù)
  • shutdownNow():立即終止線程池,并嘗試打斷正在執(zhí)行的任務(wù),并且清空任務(wù)緩存隊(duì)列,返回尚未執(zhí)行的任務(wù)

7.線程池容量的動(dòng)態(tài)調(diào)整

  ThreadPoolExecutor提供了動(dòng)態(tài)調(diào)整線程池容量大小的方法:setCorePoolSize()和setMaximumPoolSize(),

  • setCorePoolSize:設(shè)置核心池大小
  • setMaximumPoolSize:設(shè)置線程池最大能創(chuàng)建的線程數(shù)目大小

  當(dāng)上述參數(shù)從小變大時(shí),ThreadPoolExecutor進(jìn)行線程賦值,還可能立即創(chuàng)建新的線程來(lái)執(zhí)行任務(wù)。

?

轉(zhuǎn)載于:https://www.cnblogs.com/chappell/p/9084496.html

創(chuàng)作挑戰(zhàn)賽新人創(chuàng)作獎(jiǎng)勵(lì)來(lái)咯,堅(jiān)持創(chuàng)作打卡瓜分現(xiàn)金大獎(jiǎng)

總結(jié)

以上是生活随笔為你收集整理的Java面试——线程池的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。

如果覺(jué)得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。