Java Util Concurrent并發(fā)編程(三)阻塞隊列和線程池

之前簡單的介紹了一些并發(fā)的基礎知識。還用實際代碼證實了常用集合類的不安全。另外也簡單說了下Concurrent中的常用的幾個輔助類吗货。今天這篇文章主要是簡單介紹下與Lock同等級的讀寫鎖還有隊列。

ReadWriteLock

讀寫鎖是個接口,我們先去手冊中簡單看下這個介紹:


ReadWriteLock簡單介紹

其實這個讀不加鎖寫加鎖的設計在好多地方都有涉及鹃祖。比如數(shù)據(jù)庫讀寫分離。還有緩存是寫入的時候更新普舆。讀的話不更新恬口。種種行為都告訴我們讀和寫是不一樣的。其實這個也好理解沼侣,寫入操作會使得數(shù)據(jù)發(fā)生變化祖能。種種臟讀幻讀不可重復讀的原因都是寫入導致的!(準確的說是讀寫時機導致的蛾洛。但是本質(zhì)上還是因為寫改動數(shù)據(jù)了芯杀。不然重復讀百萬次也不會發(fā)生錯誤啊Q盘丁)所以讀寫鎖就是針對這一事實情況很人性化的一個設計:其實我們通俗理解揭厚,是不是就是寫的時候加鎖,讀的時候不用加鎖胺龉筛圆?它的設計特別簡單,只有兩個方法:


ReadWriteLock方法

我們理解了讀寫鎖是什么接下來還要知道是怎么實現(xiàn)的椿浓,怎么使用它太援。
首先正常在多線程的寫入中,肯定會同時寫入多個扳碍,這個是很容易理解的提岔。附上demo代碼:

沒有任何安全措施的情況下寫是不安全的

而讀寫鎖可以讓我們的寫入變得安全:
使用寫鎖讓寫操作更安全

至于讀鎖,是可以同時執(zhí)行的笋敞,如下截圖:
讀鎖

基于以上讀寫鎖的特性碱蒙。寫鎖也被稱為獨占鎖。因為是同時只能有一個線程占有。而讀鎖也被稱為共享鎖赛惩“梗可以好多線程共享。

阻塞隊列

其實這個組賽隊列是可以分成兩個詞的:阻塞喷兼。隊列篮绰。
隊列:Queue,這個稍微理解點數(shù)據(jù)結構的都應該知道季惯,在中國排隊應該處處都在吠各,買票,排網(wǎng)紅店勉抓,食堂打飯等等走孽。一個顯著的特點就是先入先出。先排隊的人先辦業(yè)務這個很好理解琳状。
阻塞:這個概念不是很好理解磕瓷。但是我們換一個詞:阻止。就好理解多了念逞。比如去銀行辦業(yè)務困食,人家快下班了,就會阻止你排隊翎承,說別排了硕盹,今天辦不了了,明天早點來吧叨咖。你看你被阻止了是不是瘩例。排隊被阻止其實分兩種情況:一種是排隊的人夠了,不讓你排了甸各。還有一種是排隊的目標沒了(上面說的辦理業(yè)務的人下班了)不讓你排了垛贤。落實到Queue種,也是如下兩種情況:

  • 寫入:隊列滿了趣倾,必須阻塞等待聘惦。
  • 讀取:如果是隊列是空的儒恋,比如阻塞等待生產(chǎn)善绎。

上面說的兩種情況都是不得不阻塞。
下面我們?nèi)タ纯垂俜绞謨苑N對阻塞隊列的介紹:


阻塞隊列

其實這個類我們應該很熟悉诫尽。因為我們經(jīng)常用它的叔叔伯伯禀酱。附上類關系圖:


Collection家族

看了這個圖我們有沒有對這個阻塞隊列更加清晰一點:其實這個也算是集合家族的三代直系了。說它的本質(zhì)就是個集合其實也沒錯牧嫉。只不過這個集合不同于Set的無序唯一剂跟,List的散列或鏈表。而是一個先入先出的展現(xiàn)形式而已。而我們現(xiàn)在說的阻塞隊列是Queue的一個兒子浩聋,它的兄弟賊多观蜗。我簡單把我知道的標出來了臊恋,附上一個家族成員圖:
我知道的都標出來了衣洁,不準確歡迎指出

一般我們什么時候用阻塞隊列呢?多用于多線程并發(fā)處理抖仅,線程池之類的坊夫。

而隊列的使用其實和List,Set是差不多的撤卢。主要操作就是添加移除环凿。但是這里比較特殊,涉及到很多東西放吩。比如隊列滿了再添加是報錯啊智听,還是不報錯只返回false還是說把第一個自動出列(擠走)。同樣如果隊列空了再取值是怎么樣渡紫?返回null還是報錯到推?下面我們代碼種一個個嘗試一下。

  • 拋出異常的方法
    add當隊列滿了會報錯惕澎。

    remove當隊列空了會報錯

    獲取隊首元素而不出隊莉测,無元素報錯
  • 有返回值不拋出異常的方法
    offer添加隊列滿了返回false

    poll移除隊列空了返回null

    獲取隊首元素而不出隊。無元素返回null
  • 一直等待(一直阻塞)
    添加的時候隊列滿了一直等待

    拿取的時候隊列空了一直等待
  • 等待超時(等一定時間就不等了)
    我們可以看到offer方法是有個重載方法唧喉,帶有超時時間的

    等待

    poll同樣可以選擇等一段時間

    poll的等待

以上4*2組存取捣卤。兩個獲取隊首元素而不出隊。一共十個api其實要根據(jù)實際情況使用八孝。都是比較常用的董朝,也比較好記。每個人都應該掌握干跛。

SynchronousQueue 同步隊列

這個其實比較好理解:就是沒有容量益涧。一次只能放一個元素。下面可以在代碼中看看:


只有一個是不是公平的參數(shù)

時間間隔5m說明一個先出隊再入隊的

這個demo就說明了SynchronousQueue 同步隊列的特性:只能存儲一個元素驯鳖。上一個出去了這個才能進去闲询。

線程池

池化技術:池化技術能夠減少資源對象的創(chuàng)建次數(shù),提高程序的性能浅辙,特別是在高并發(fā)下這種提高更加明顯扭弧。使用池化技術緩存的資源對象有如下共同特點:

  1. 對象創(chuàng)建時間長;
  2. 對象創(chuàng)建需要大量資源记舆;
  3. 對象創(chuàng)建后可被重復使用鸽捻。

我們在工作中:線程池,連接池,內(nèi)存池御蒲,對象池都是如此衣赶。
而線程池的好處:

  1. 降低資源消耗
  2. 提高響應速度
  3. 方便管理

下面我們詳細的講一下線程池。

線程池三大方法:

其實說到三大方法有一個工具類繞不過去了厚满,我們可以去官方手冊上看一下府瞄。叫做Executors.下面是官方手冊中的介紹:

Executors工具類

其實這個類就好像Collections于集合。這個類也是一個單純的工具類碘箍。主要是可以創(chuàng)建一些默認的線程池遵馆。
Executors的方法

而常用的三大方法也在這里,下面代碼一個個說明:
單例線程 Executors.newSingleThreadExecutor();
事實證明這個線程池只有一個線程在執(zhí)行

指定大小的線程池 Executors.newFixedThreadPool(n);(n是指定的線程數(shù))
每次有四個線程執(zhí)行

創(chuàng)建一個大小可伸縮的線程池 newCachedThreadPool
一次一萬個線程也都跑了

其實關于這個要說一下丰榴,雖然是大小可伸縮货邓。但是也不能無限大啊。哪怕線程池受得了你這個cpu也受不了吧四濒。我們點進去看下這個方法的源碼:
無參可伸縮的線程池源碼

如果到這你還沒才出來這個Integer.MAX_VALUE是啥换况,我們繼續(xù)往下走:
最大線程數(shù)量二十多億

說真的這個方法不要就這么用,建議還是設置一個合理的數(shù)值盗蟆。畢竟一大波并發(fā)服務器都得沖廢了戈二。
其實我們可以挨個方法點進去看一波源碼:
單例線程的源碼

定長線程池源碼

那個可伸縮的上面已經(jīng)看過了,是不是三個方法最終落實到的方法都是ThreadPoolExecutor澳飞挽拂?
而且本質(zhì)上也就是這個方法的參數(shù)不同。下面我們?nèi)シ治龇治鲞@個方法和參數(shù)骨饿。

線程池七個參數(shù)

線程池的三大方法已經(jīng)說過了亏栈,下面說七大參數(shù):


ThreadPoolExecutor源碼中是紅色框起來的五個+藍色的兩個,一共七個參數(shù)

下面一個個參數(shù)說一下:

  • int corePoolSize 核心線程數(shù)
  • int maximumPoolSize 最大線程數(shù)
  • long keepAliveTime 等待時間
  • TimeUnit unit 等待時間的時間單位
  • BlockingQueue<Runnable> workQueue 一個阻塞隊列宏赘。
  • Executors.defaultThreadFactory() 默認的線程工廠
  • defaultHandler 拒絕策略

這塊用現(xiàn)實中的例子簡單介紹下:如果說線程池就是銀行绒北。那么核心線程數(shù)就是銀行的常年開的窗口。而最大線程數(shù)就是銀行有的窗口(一般銀行不會把所有窗口都開著察署,尤其是人少的時候)闷游。而阻塞隊列就是除了正在辦理業(yè)務的人以外等待的人。當?shù)却娜说竭_一定程度(隊列滿了)贴汪,銀行會臨時開幾個窗口來辦理業(yè)務的脐往。但是當人少了以后,臨時窗口沒人辦理業(yè)務扳埂。在等待一段時間后就會繼續(xù)關閉业簿。等著下次人多了再開。而拒絕策略是如果所有的窗口都開了阳懂,而且等待區(qū)也滿了梅尤,這個時候還有人要進來肯定是進不來了柜思,是讓在門口等著還是給攆回去,這個措施就是拒絕策略巷燥!

線程池四種拒絕策略

四種拒絕策略(new ThreadPoolExecutor.出來的):

  • AbortPolicy 隊列滿了還有人進來,會拋出異常(默認)
  • DiscardPolicy 隊列滿了會丟掉任務,不會拋出異常
  • DiscardOldestPolicy 隊列滿了會嘗試和最早的競爭,也不會拋出異常.
  • CallerRunsPolicy 哪來的回哪去.沒有異常,沒有行為.
線程池調(diào)優(yōu)

線程池的大小到底如何設置?

  1. CPU密集型:幾核就是幾線程赡盘。可以保持CPU的效率最高缰揪。(ps:這里不要只看當前開發(fā)環(huán)境的電腦陨享,因為服務器會性能比開發(fā)環(huán)境好的多,建議用代碼獲取邀跃。)
//此方法打印可用處理器的虛擬機的最大數(shù)量
System.out.println(Runtime.getRuntime().availableProcessors());
  1. IO密集型:程序中有很多耗io的線程(因為io本身比較慢)要設置大于IO任務的線程霉咨。

本篇筆記就記到這里蛙紫,如果稍微幫到你了記得點個喜歡點個關注拍屑,也祝大家工作順順利利!

?著作權歸作者所有,轉載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末坑傅,一起剝皮案震驚了整個濱河市僵驰,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌唁毒,老刑警劉巖蒜茴,帶你破解...
    沈念sama閱讀 222,378評論 6 516
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異浆西,居然都是意外死亡粉私,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,970評論 3 399
  • 文/潘曉璐 我一進店門近零,熙熙樓的掌柜王于貴愁眉苦臉地迎上來诺核,“玉大人,你說我怎么就攤上這事久信〗焉保” “怎么了?”我有些...
    開封第一講書人閱讀 168,983評論 0 362
  • 文/不壞的土叔 我叫張陵裙士,是天一觀的道長入客。 經(jīng)常有香客問我,道長腿椎,這世上最難降的妖魔是什么桌硫? 我笑而不...
    開封第一講書人閱讀 59,938評論 1 299
  • 正文 為了忘掉前任,我火速辦了婚禮啃炸,結果婚禮上铆隘,老公的妹妹穿的比我還像新娘。我一直安慰自己肮帐,他們只是感情好咖驮,可當我...
    茶點故事閱讀 68,955評論 6 398
  • 文/花漫 我一把揭開白布边器。 她就那樣靜靜地躺著,像睡著了一般托修。 火紅的嫁衣襯著肌膚如雪忘巧。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 52,549評論 1 312
  • 那天睦刃,我揣著相機與錄音砚嘴,去河邊找鬼。 笑死涩拙,一個胖子當著我的面吹牛际长,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播兴泥,決...
    沈念sama閱讀 41,063評論 3 422
  • 文/蒼蘭香墨 我猛地睜開眼工育,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了搓彻?” 一聲冷哼從身側響起如绸,我...
    開封第一講書人閱讀 39,991評論 0 277
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎旭贬,沒想到半個月后怔接,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 46,522評論 1 319
  • 正文 獨居荒郊野嶺守林人離奇死亡稀轨,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 38,604評論 3 342
  • 正文 我和宋清朗相戀三年扼脐,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片奋刽。...
    茶點故事閱讀 40,742評論 1 353
  • 序言:一個原本活蹦亂跳的男人離奇死亡瓦侮,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出杨名,到底是詐尸還是另有隱情脏榆,我是刑警寧澤,帶...
    沈念sama閱讀 36,413評論 5 351
  • 正文 年R本政府宣布台谍,位于F島的核電站须喂,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏趁蕊。R本人自食惡果不足惜坞生,卻給世界環(huán)境...
    茶點故事閱讀 42,094評論 3 335
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望掷伙。 院中可真熱鬧是己,春花似錦、人聲如沸任柜。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,572評論 0 25
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至摔认,卻和暖如春藕咏,著一層夾襖步出監(jiān)牢的瞬間邮利,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,671評論 1 274
  • 我被黑心中介騙來泰國打工割笙, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留贷揽,地道東北人颇玷。 一個月前我還...
    沈念sama閱讀 49,159評論 3 378
  • 正文 我出身青樓植影,卻偏偏與公主長得像郭变,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子环壤,可洞房花燭夜當晚...
    茶點故事閱讀 45,747評論 2 361

推薦閱讀更多精彩內(nèi)容