并發(fā)編程的原理分析

什么是多線程云芦?

多線程是利用cpu的多核心技術徽级,使多線程實現(xiàn)線程的并發(fā)執(zhí)行

java四種線程池

newCachedThreadPool

創(chuàng)建可緩存的線程底扳,底層是依靠 SynchronousQueue?實現(xiàn)的,創(chuàng)建線程數(shù)量幾乎沒有限制(最大為 Integer.MAX_VALUE)奏瞬。如果長時間沒有往線程池提交任務,即如果工作線程空閑了指定時間(默認1分鐘)泉孩,該工作線程自動終止硼端。終止后如果又有了新的任務,則會創(chuàng)建新的線程寓搬。在使用 CachedTreadPool 時珍昨,要注意控制任務數(shù)量,否則由于大量線程同時運行句喷,很有可能造成系統(tǒng)癱瘓镣典。

newFixedThreadPool

創(chuàng)建指定數(shù)量的工作線程,底層是依靠 LinkedBlockingQueue 實現(xiàn)的唾琼,沒提交一個任務就創(chuàng)建一個工作線程兄春,當工作線程數(shù)量達到線程池初始的最大數(shù),則將提交的任務存入到池隊列中锡溯。在線程空閑時赶舆,不會釋放工作線程肴裙,還會占用一定的系統(tǒng)資源。

newSingleThreadExecutor

創(chuàng)建單線程涌乳,底層是?LinkedBlockingQueue 實現(xiàn)的蜻懦,它只會用一個工作線程來執(zhí)行任務,保證所有的任務按指定順序執(zhí)行夕晓。如果這個線程異常結束宛乃,會有另一個取代它,保證順序執(zhí)行蒸辆。最大的特點是可保證順序地執(zhí)行各個任務征炼,并在任意時間是不會有過個線程活動的。

newScheduleThreadPool

?創(chuàng)建一個定長的線程池躬贡,支持定時以及周期性的任務調度谆奥。

線程池工作原理

一? 線程池創(chuàng)建


線程池七個基本參數(shù)

1、corePoolSize

線程池的核心線程數(shù)拂玻,每個線程都會存在即使沒有任何工作也會在等任務

2酸些、maximumPoolSize

最大線程數(shù),線程池的上限

3檐蚜、keepAliveTime

線程的存活時間魄懂。當線程池里的線程數(shù)大于corePoolSize時,如果等了keepAliveTime時長還沒有任務可執(zhí)行闯第,則線程退出

4市栗、unit

指定的線程存活時間,比如秒:TimeUnit.SECONDS咳短。

5填帽、workQueue

一個阻塞隊列提交的任務會放到這個隊列里

6、threadFactory

線程工廠咙好,用來創(chuàng)建線程篡腌,主要是為了給線程起名字,默認工廠的線程名字:pool-1-thread-3敷扫。

7哀蘑、handler

拒絕策略,當線程池里線程被耗盡葵第,且隊列也滿了的時候會調用绘迁。

二、線程池執(zhí)行流程

線程池工作流程簡圖

說明

1卒密、提交任務當向線程池提交一個新的任務時缀台,線程池有三種處理情況,分別是:創(chuàng)建一個工作線程來執(zhí)行該任務哮奇、將任務加入阻塞隊列膛腐、拒絕該任務睛约。提交任務的過程也可以拆分成以下幾個部分:當工作線程數(shù)小于核心線程數(shù)時,直接創(chuàng)建新的核心工作線程當工作線程數(shù)不小于核心線程數(shù)時哲身,就需要嘗試將任務添加到阻塞隊列中去如果能夠加入成功辩涝,說明隊列還沒有滿,那么需要做以下的二次驗證來保證添加進去的任務能夠成功被執(zhí)行驗證當前線程池的運行狀態(tài)勘天,如果是非RUNNING狀態(tài)怔揩,則需要將任務從阻塞隊列中移除,然后拒絕該任務驗證當前線程池中的工作線程的個數(shù)脯丝,如果為0商膊,則需要主動添加一個空工作線程來執(zhí)行剛剛添加到阻塞隊列中的任務如果加入失敗,則說明隊列已經(jīng)滿了宠进,那么這時就需要創(chuàng)建新的“臨時”工作線程來執(zhí)行任務如果創(chuàng)建成功晕拆,則直接執(zhí)行該任務如果創(chuàng)建失敗,則說明工作線程數(shù)已經(jīng)等于最大線程數(shù)了材蹬,則只能拒絕該任務了整個過程可以用下面這張圖來表示:

拒絕任務簡圖

2实幕、創(chuàng)建工作線程創(chuàng)建工作線程需要做一系列的判斷,需要確保當前線程池可以創(chuàng)建新的線程之后赚导,才能創(chuàng)建茬缩。首先赤惊,當線程池的狀態(tài)是 SHUTDOWN 或者 STOP 時吼旧,則不能創(chuàng)建新的線程。另外未舟,當線程工廠創(chuàng)建線程失敗時圈暗,也不能創(chuàng)建新的線程。還有就是當前工作線程的數(shù)量與核心線程數(shù)裕膀、最大線程數(shù)進行比較员串,如果前者大于后者的話,也不允許創(chuàng)建昼扛。除此之外寸齐,會嘗試通過 CAS 來自增工作線程的個數(shù),如果自增成功了抄谐,則會創(chuàng)建新的工作線程渺鹦,即 Worker 對象。然后加鎖進行二次驗證是否能夠創(chuàng)建工作線程蛹含,最后如果創(chuàng)建成功毅厚,則會啟動該工作線程。3浦箱、啟動工作線程當工作線程創(chuàng)建成功后吸耿,也就是 Worker 對象已經(jīng)創(chuàng)建好了祠锣,這時就需要啟動該工作線程,讓線程開始干活了咽安,Worker 對象中關聯(lián)著一個 Thread伴网,所以要啟動工作線程的話,只要通過 worker.thread.start() 來啟動該線程即可妆棒。啟動完了之后是偷,就會執(zhí)行 Worker 對象的 run 方法,因為 Worker 實現(xiàn)了 Runnable 接口募逞,所以本質上 Worker 也是一個線程蛋铆。通過線程 start 開啟之后就會調用到 Runnable 的 run 方法,在 worker 對象的 run 方法中放接,調用了 runWorker(this) 方法刺啦,也就是把當前對象傳遞給了 runWorker 方法,讓他來執(zhí)行纠脾。4玛瘸、獲取任務并執(zhí)行在 runWorker 方法被調用之后,就是執(zhí)行具體的任務了苟蹈,首先需要拿到一個可以執(zhí)行的任務糊渊,而 Worker 對象中默認綁定了一個任務,如果該任務不為空的話慧脱,那么就是直接執(zhí)行渺绒。執(zhí)行完了之后,就會去阻塞隊列中獲取任務來執(zhí)行菱鸥,而獲取任務的過程宗兼,需要考慮當前工作線程的個數(shù)。如果工作線程數(shù)大于核心線程數(shù)氮采,那么就需要通過 poll 來獲取殷绍,因為這時需要對閑置的線程進行回收;如果工作線程數(shù)小于等于核心線程數(shù)鹊漠,那么就可以通過 take 來獲取了主到,因此這時所有的線程都是核心線程,不需要進行回收躯概,前提是沒有設置 allowCoreThreadTimeOut

什么是CAS(compare and swap)登钥?

CAS流程圖解

CAS 最終指令:lock(原子性,當執(zhí)行cmpxchg 操作時楞陷,當前cpu不予許修改) cmpxchg (非原子性)

ThreadLocal作用

ThreadLocal提供了線程本地變量怔鳖,它可以保證訪問到的變量屬于當前線程,每個線程都保存有一個變量副本,每個線程的變量都不同结执。ThreadLocal相當于提供了一種線程隔離度陆,將變量與線程相綁定。

volatile作用

1献幔、防止指令重排序

2懂傀、lock

volatile/synchronize? --> lock指令

1.把當前處理器緩存行的數(shù)據(jù)寫會系統(tǒng)內存

2.使得cpu內的緩存地址失效

Java強軟弱虛四中引用的使用場景

一、引用強度排序

強引用>軟引用>弱引用>虛引用

二蜡感、強引用:

1. 正常創(chuàng)建的對象蹬蚁,只要引用存在,永遠不會被GC回收郑兴,即使OOM

Object obj = new Object();

2. 如果要中斷強引用和某個對象的關聯(lián)犀斋,為其賦值null,這樣GC就會在合適的時候回收對象

3. Vector類的clear()方法就是通過賦值null進行清除

三情连、軟引用

1. 內存溢出之前進行回收叽粹,GC時內存不足時回收,如果內存足夠就不回收

2. 使用場景:在內存足夠的情況下進行緩存却舀,提升速度虫几,內存不足時JVM自動回收

Object obj = new Object();

SoftReference sf = new SoftReference(obj);

sf.get();//有時候會返回null

3. 可以和引用隊列ReferenceQueue聯(lián)合使用,如果軟引用所引用的對象被JVM回收挽拔,這個軟引用就會被加入到與之關聯(lián)的引用隊列中

四辆脸、弱引用

1. 每次GC時回收,無論內存是否足夠

2. 使用場景:a. ThreadLocalMap防止內存泄漏 ?b. 監(jiān)控對象是否將要被回收

Object obj = new Object();

WeakReference wf = new WeakReference(obj);

wf.get();//有時候會返回null

wf.isEnQueued();//返回是否被垃圾回收器標記為即將回收的垃圾

System.gc(); ?//通知JVM的gc進行垃圾回收螃诅,但JVM不一定會立刻執(zhí)行

wf.get();//此時會返回null

3.?弱引用可以和一個引用隊列(ReferenceQueue)聯(lián)合使用啡氢,如果弱引用所引用的對象被JVM回收,這個軟引用就會被加入到與之關聯(lián)的引用隊列中

五州刽、虛引用

1. 每次垃圾回收時都會被回收空执,主要用于監(jiān)測對象是否已經(jīng)從內存中刪除

2.?虛引用必須和引用隊列關聯(lián)使用,?當垃圾回收器準備回收一個對象時,如果發(fā)現(xiàn)它還有虛引用穗椅,就會把這個虛引用加入到與之 關聯(lián)的引用隊列中

3.?程序可以通過判斷引用隊列中是否已經(jīng)加入了虛引用,來了解被引用的對象是否將要被垃圾回收奶栖。如果程序發(fā)現(xiàn)某個虛引用已經(jīng)被加入到引用隊列匹表,那么就可以在所引用的對象的內存被回收之前采取必要的行動

Object obj = new Object();

PhantomReference pf = new PhantomReference(obj);

obj=null;

pf.get();//永遠返回null

pf.isEnQueued();//返回是否從內存中已經(jīng)刪除

線程、進程宣鄙、內存袍镀、cpu架構圖

線程、進程冻晤、內存苇羡、cpu架構圖?

CPU的核心數(shù)、線程數(shù)的關系和區(qū)別

關系:

1鼻弧、線程數(shù)可以模擬出不同的CPU核心數(shù)设江。

CPU的核數(shù)是指硬件上有多個核锦茁,線程數(shù)可以模擬多個核的功能。線程越多叉存,就越有利于同時運行多個程序码俩,因為線程數(shù)等于CPU在某一時刻可以同時并行處理的任務數(shù)。

2歼捏、對于一個CPU,線程數(shù)總是大于或等于核心數(shù)的瞳秽。一個內核至少對應一個線程瓣履,但通過超線程技術练俐,一個內核可以對應兩個線程,即可以同時運行兩個線程痰洒。

區(qū)別:

1瓢棒、不同的存在形式

(1)CPU的核心數(shù)是指硬件上的真實對象丘喻。

(2)CPU線程數(shù)只是一個邏輯概念,不是一個真正的對象泉粉,只是為了更好地描述CPU的運行能力。

2嗡靡、線程數(shù)對于不同的CPU類型存在不同的狀態(tài)

(1)對于英特爾CPU:除了核心數(shù)之外跺撼,還可以使用線程數(shù)的概念讨彼,因為它是通過英特爾超線程技術實現(xiàn)的歉井。

(2)對于AMDCPU:只有內核數(shù),沒有線程數(shù)的概念哈误。因為AMDCPU沒有超線程技術哩至,一個CPU核對應一個線程。

3蜜自、出現(xiàn)原因不同

(1)核心數(shù)產(chǎn)生的原因:提高處理器主頻的技術遇到了瓶頸菩貌。為了在“多核”的方向上發(fā)展,現(xiàn)有的產(chǎn)品可以發(fā)展成一個具有更強大理論性能而沒有大規(guī)模發(fā)展的多核處理器系統(tǒng)重荠。因此箭阶,“核心數(shù)”一詞應運而生。

(2)線程數(shù)量的原因:為了進一步提高計算機的多任務處理能力。線程越多仇参,同時運行多個程序就越好嘹叫。

參考:

https://www.cnblogs.com/yw-ah/p/5830458.html

https://www.cnblogs.com/dolphin0520/p/3784171.html

https://blog.csdn.net/u_my_heart/article/details/90648193

?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市冈敛,隨后出現(xiàn)的幾起案子待笑,更是在濱河造成了極大的恐慌,老刑警劉巖抓谴,帶你破解...
    沈念sama閱讀 212,454評論 6 493
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件暮蹂,死亡現(xiàn)場離奇詭異,居然都是意外死亡癌压,警方通過查閱死者的電腦和手機仰泻,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,553評論 3 385
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來滩届,“玉大人集侯,你說我怎么就攤上這事≈南” “怎么了棠枉?”我有些...
    開封第一講書人閱讀 157,921評論 0 348
  • 文/不壞的土叔 我叫張陵,是天一觀的道長泡挺。 經(jīng)常有香客問我辈讶,道長,這世上最難降的妖魔是什么娄猫? 我笑而不...
    開封第一講書人閱讀 56,648評論 1 284
  • 正文 為了忘掉前任贱除,我火速辦了婚禮,結果婚禮上媳溺,老公的妹妹穿的比我還像新娘月幌。我一直安慰自己,他們只是感情好悬蔽,可當我...
    茶點故事閱讀 65,770評論 6 386
  • 文/花漫 我一把揭開白布扯躺。 她就那樣靜靜地躺著,像睡著了一般屯阀。 火紅的嫁衣襯著肌膚如雪缅帘。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 49,950評論 1 291
  • 那天难衰,我揣著相機與錄音,去河邊找鬼逗栽。 笑死盖袭,一個胖子當著我的面吹牛,可吹牛的內容都是我干的。 我是一名探鬼主播鳄虱,決...
    沈念sama閱讀 39,090評論 3 410
  • 文/蒼蘭香墨 我猛地睜開眼弟塞,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了拙已?” 一聲冷哼從身側響起决记,我...
    開封第一講書人閱讀 37,817評論 0 268
  • 序言:老撾萬榮一對情侶失蹤倍踪,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后扩借,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體缤至,經(jīng)...
    沈念sama閱讀 44,275評論 1 303
  • 正文 獨居荒郊野嶺守林人離奇死亡领斥,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 36,592評論 2 327
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了何恶。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片膊存。...
    茶點故事閱讀 38,724評論 1 341
  • 序言:一個原本活蹦亂跳的男人離奇死亡隔崎,死狀恐怖,靈堂內的尸體忽然破棺而出爵卒,到底是詐尸還是另有隱情,我是刑警寧澤实牡,帶...
    沈念sama閱讀 34,409評論 4 333
  • 正文 年R本政府宣布轴合,位于F島的核電站,受9級特大地震影響题涨,放射性物質發(fā)生泄漏。R本人自食惡果不足惜纲堵,卻給世界環(huán)境...
    茶點故事閱讀 40,052評論 3 316
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望铐望。 院中可真熱鬧茂附,春花似錦、人聲如沸何之。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,815評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽蒜危。三九已至,卻和暖如春部翘,著一層夾襖步出監(jiān)牢的瞬間响委,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 32,043評論 1 266
  • 我被黑心中介騙來泰國打工夹囚, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留邀窃,地道東北人。 一個月前我還...
    沈念sama閱讀 46,503評論 2 361
  • 正文 我出身青樓鞍历,卻偏偏與公主長得像肪虎,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子扇救,可洞房花燭夜當晚...
    茶點故事閱讀 43,627評論 2 350