Java面試——線程池

1、類比介紹

  假如有一個工廠,工廠里面有10個工人,每個工人同時只能做一件任務。

  因此只要當10個工人中有工人是空閑的,來了任務就分配給空閑的工人做;

  當10個工人都有任務在做時,如果還來了任務,就把任務進行排隊等待;

  如果說新任務數目增長的速度遠遠大于工人做任務的速度,那么此時工廠主管可能會想補救措施,比如重新招4個臨時工人進來;

  然后就將任務也分配給這4個臨時工人做;

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

  當這14個工人當中有人空閑時,而新任務增長的速度又比較緩慢,工廠主管可能就考慮辭掉4個臨時工了,只保持原來的10個工人,畢竟請額外的工人是要花錢的。

?

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

  也就是說corePoolSize就是線程池大小,maximumPoolSize在我看來是線程池的一種補救措施,即任務量突然過大時的一種補救措施。

2、源碼分析

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

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方法中,首先用提交的任務創建了一個Worker對象,然后調用線程工廠threadFactory創建了一個新的線程t,然后將線程t的引用賦值給了Worker對象的成員變量thread,接著通過workers.add(w)將Worker對象添加到工作集當中。

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

?

下面總結一下:

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

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

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

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

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

  默認情況下,創建線程池之后,線程池中是沒有線程的,需要提交任務之后才會創建線程。

  在實際中如果需要線程池創建之后立即創建線程,可以通過以下兩個方法辦到:

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

?

4.任務緩存隊列及排隊策略

  在前面我們多次提到了任務緩存隊列,即workQueue,它用來存放等待執行的任務。

  workQueue的類型為BlockingQueue<Runnable>,通常可以取下面三種類型:

  1)ArrayBlockingQueue:基于數組的先進先出隊列,此隊列創建時必須指定大小;

  2)LinkedBlockingQueue:基于鏈表的先進先出隊列,如果創建時沒有指定此隊列大小,則默認為Integer.MAX_VALUE;

  3)synchronousQueue:這個隊列比較特殊,它不會保存提交的任務,而是將直接新建一個線程來執行新來的任務。

?

5.任務拒絕策略

當線程池的任務緩存隊列已滿并且線程池中的線程數目達到maximumPoolSize,如果還有任務到來就會采取任務拒絕策略,通常有以下四種策略:

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

6.線程池的關閉

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

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

7.線程池容量的動態調整

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

  • setCorePoolSize:設置核心池大小
  • setMaximumPoolSize:設置線程池最大能創建的線程數目大小

  當上述參數從小變大時,ThreadPoolExecutor進行線程賦值,還可能立即創建新的線程來執行任務。

?

轉載于:https://www.cnblogs.com/chappell/p/9084496.html

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/452184.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/452184.shtml
英文地址,請注明出處:http://en.pswp.cn/news/452184.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

C#關鍵字的使用

params object[] 用于函數多參數的定義public static void Write(string format, params object[] arg);explicit 關鍵字用于聲明必須使用強制轉換來調用的用戶定義的類型轉換運算符。 例如&#xff0c;在下面的示例中&#xff0c;此運算符將名為 Fahrenheit 的類轉換為名為 Ce…

maven 中 pom.xml 配置文件標簽說明,dependencyManagement和dependencies區別

前些天發現了一個巨牛的人工智能學習網站&#xff0c;通俗易懂&#xff0c;風趣幽默&#xff0c;忍不住分享一下給大家。點擊跳轉到教程。 參考&#xff1a;http://zhaoshijie.iteye.com/blog/2094478http://blog.csdn.net/cpf2016/article/details/45674377 還有一篇轉載文章…

學成在線--17.我的課程

文章目錄一.需求分析二.API接口三.PageHelper1.PageHelper介紹2.添加依賴3.配置pageHelper四.Dao1.mapper 接口2.mapper.xml映射文件3.測試Dao五.Service六.Controller七.前端1.創建course_list.vue2.路由3.定義API方法4.前端視圖course_list.vue詳解1&#xff09;API調用--在視…

碼是數據系統中的基本概念。所謂碼就是能唯一標識實體的屬性或屬性集合&#xff0c;他是整個實體集的性質&#xff0c;而不是單個實體的性質。 主屬性與非主屬性 包含在任何一個候選碼中的屬性 &#xff0c;稱為主屬性&#xff08;Prime attribute&#xff09;。 不包含在任何…

關于C編程的一點感受

剛畢業的時候用了兩個多月的C語言編程&#xff0c;總的來說對它還是很有感受的&#xff0c;C是一個過程式語言&#xff0c;沒有像C,Java等OOP語言這樣那樣的一系列的規則和限制&#xff1b;它比較靈活&#xff0c;簡潔&#xff0c;高效&#xff1b;這些是給我的印象最深的。這是…

如何打造高效的多任務、高并發的網絡服務器系統?

同一個功能的軟件&#xff0c;不同的團隊&#xff0c;不同工程師去實現&#xff0c;肯定是千差萬別&#xff0c;甚至從根本上完全不同。所以軟件開發在未來很長時間內仍然是一項工匠的手工勞動&#xff0c;尤其像多任務&#xff0c;高并發&#xff0c;偏底層這種對實現技巧比較…

BZOJ.2780.[SPOJ8093]Sevenk Love Oimaster(廣義后綴自動機)

題目鏈接 \(Description\) 給定n個模式串&#xff0c;多次詢問一個串在多少個模式串中出現過。(字符集為26個小寫字母) \(Solution\) 對每個詢問串進行匹配最終會達到一個節點&#xff0c;我們需要得到這個節點所代表的子串出現在多少個模式串中。 建立廣義后綴自動機。每次插入…

BigDecimal 加減乘除運算

前些天發現了一個巨牛的人工智能學習網站&#xff0c;通俗易懂&#xff0c;風趣幽默&#xff0c;忍不住分享一下給大家。點擊跳轉到教程。 java.math.BigDecimal。BigDecimal一共有4個夠造方法&#xff0c;讓我先來看看其中的兩種用法&#xff1a; 第一種&#xff1a;BigDeci…

主碼 超碼 候選碼

碼是數據系統中的基本概念。所謂碼就是能唯一標識實體的屬性&#xff0c;他是整個實體集的性質&#xff0c;而不是單個實體的性質。它包括超碼&#xff0c;候選碼&#xff0c;主碼。   超碼是一個或多個屬性的集合&#xff0c;這些屬性可以讓我們在一個實體集中唯一地標識一…

學成在線--18.新增課程(課程分類查詢)

文章目錄一.需求分析二.課程分類查詢介紹三.數據結構四.數據格式五.數據模型六.Api接口七.服務器端1.Dao1&#xff09;定義mapper2&#xff09;定義mapper映射文件2.Service3.Controller八.接口測試一.需求分析 用戶操作流程如下&#xff1a; 1、用戶進入“我的課程”頁面&…

給程序員們的工資報價提醒

在薪水上討價還價的方式有很多種&#xff0c;我要說的這一點也許并不是最好的。然而&#xff0c;如果使用的得當&#xff0c;會收到很好的效果。如果你正在跟一家公司接觸(沒有經過職業中介)&#xff0c;而且事情看來很順利&#xff0c;進度很快&#xff0c;你要保持這種面試的…

POI 方式-excle 表格導出實現-java-poi

前些天發現了一個巨牛的人工智能學習網站&#xff0c;通俗易懂&#xff0c;風趣幽默&#xff0c;忍不住分享一下給大家。點擊跳轉到教程。 效果&#xff1a; jsp 頁面 用的Bootstrap &#xff1a; <li class"dropdown"> <a href"javascript:void(0)…

02-css的選擇器

css的選擇器&#xff1a;1.基本選擇器 2.高級選擇器 基本選擇器包含&#xff1a; 1.標簽選擇器標簽選擇器可以選中所有的標簽元素&#xff0c;比如div&#xff0c;ul&#xff0c;li &#xff0c;p等等&#xff0c;不管標簽藏的多深&#xff0c;都能選中&#xff0c;選中的是所有…

iphoneX樣式兼容

// 1.viewport meta 標簽增加屬性viewport-fitcover // 2.body元素增加樣式 body { padding-bottom: constant(safe-area-inset-bottom); padding-bottom: env(safe-area-inset-bottom); } // 3.如有fixed底部的元素&#xff0c;也增加上面樣式 xxx { padding-bottom: constant…

學成在線--19.新增課程(數據字典)

文章目錄一.介紹二.數據模型三.數據模型類四.字典查詢API接口五.服務器端1.Dao2.Service3.Controller一.介紹 在新增課程界面需要選擇課程等級、課程狀態等&#xff0c;這些信息統一采用數據字典管理的方式。 本項目對一些業務的分類配置信息&#xff0c;比如&#xff1a;課程…

范式簡介

范式是符合某一種級別的關系模式的集合。關系數據庫中的關系必須滿足一定的要求。滿足不同程度要求的為不同范式。范式的種類&#xff1a; 第一范式(1NF) 第二范式(2NF) 第三范式(3NF) BC范式(BCNF) 第四范式(4NF) 第五范式(5NF) 一個低一級范式的關系模式&#xff0c;通過模…

程序員的進化

對于很多同學來說&#xff0c;他們對程序員的職業生涯非常關注。而這本質上是一個進化的過程。我們將如何進化&#xff1f;在每個進化階段我們應該如何提高自己&#xff1f;下面的文章根據我自己的切身經歷和閱讀過的書&#xff0c;為程序員每個階段的進化提供了不同的學習思路…

【樹形dp】vijos1144小胖守皇宮

細節很精妙 描述 huyichen世子事件后&#xff0c;xuzhenyi成了皇上特聘的御前一品侍衛。 皇宮以午門為起點&#xff0c;直到后宮嬪妃們的寢宮&#xff0c;呈一棵樹的形狀&#xff1b;某些宮殿間可以互相望見。大內保衛森嚴&#xff0c;三步一崗&#xff0c;五步一哨&#xff0c…

手機號碼歸屬地及運營商查詢

前些天發現了一個巨牛的人工智能學習網站&#xff0c;通俗易懂&#xff0c;風趣幽默&#xff0c;忍不住分享一下給大家。點擊跳轉到教程。 import java.io.InputStreamReader; import java.net.HttpURLConnection; import java.net.URL;public class NewMobile {public stati…

redhat6.5手動配置網絡

2、手動設置ip地址如果虛擬機不能自動獲取IP&#xff0c;只能手動配置&#xff0c;配置方法如下&#xff1a;輸入命令#vi /etc/sysconfig/network-scripts/ifcfg-eth0 [編輯網卡的配置文件]輸入上述命令后回車&#xff0c;打開配置文件&#xff0c;使用方向鍵移動光標到最后一行…