目錄結構:
一、CountDownLatch
閉鎖琳猫,一種非常簡單县爬、但很常用的同步輔助類。
問題一:CountDownLatch的作用是什么软族?
作用:是在完成一組正在其他線程中執(zhí)行的操作之前,允許一個或多個線程一直阻塞刷喜。
問題二:CountDownLatch的原理是什么?
原理:基于 AQS 的共享模式的使用立砸。CountDownLatch在多線程并發(fā)編程中充當一個計時器的功能掖疮,并且維護一個count的變量,并且其操作都是原子操作颗祝,該類主要通過countDown()和await()兩個方法實現(xiàn)功能的浊闪,首先通過建立CountDownLatch對象恼布,并且傳入?yún)?shù)即為count初始值。如果一個線程調用了await()方法搁宾,那么這個線程便進入阻塞狀態(tài)折汞,并進入阻塞隊列。如果一個線程調用了countDown()方法盖腿,則會使count-1爽待;當count的值為0時,這時候阻塞隊列中調用await()方法的線程便會逐個被喚醒翩腐,從而進入后續(xù)的操作鸟款。比如下面的例子就是有兩個操作,一個是讀操作一個是寫操作茂卦,現(xiàn)在規(guī)定必須進行完寫操作才能進行讀操作何什。所以當最開始調用讀操作時,需要用await()方法使其阻塞等龙,當寫操作結束時处渣,則需要使count等于0。因此count的初始值可以定為寫操作的記錄數(shù)蛛砰,這樣便可以使得進行完寫操作罐栈,然后進行讀操作。
問題三:CountDownLatch的步驟
1暴备、首先是創(chuàng)建實例 CountDownLatch countDown = new CountDownLatch(2)
2悠瞬、需要同步的線程執(zhí)行完之后,計數(shù)-1涯捻; countDown.countDown()
3浅妆、需要等待其他線程執(zhí)行完畢之后,再運行的線程障癌,調用 countDown.await()實現(xiàn)阻塞同步
舉例:
這段代碼就是10個線程同時去輸出5000以內的偶數(shù)凌外,然后在主線程那里計算執(zhí)行時間。其實這是計算不了那10個線程的執(zhí)行時間的涛浙,因為主線程與這10個線程也是同時執(zhí)行的康辑,可能那10個線程才執(zhí)行到一半,主線程就已經輸出“耗費時間為x秒”這句話了轿亮。所有要想計算這10個線程執(zhí)行的時間疮薇,就得讓主線程先等待,等10個分線程都執(zhí)行完了才能執(zhí)行主線程我注。這就要用到閉鎖按咒。看如何使用:
二但骨、CyclicBarrier
一種可重置的多路同步點励七,在某些并發(fā)編程場景很有用智袭。
問題四:CyclicBarrier的作用
作用:跟CountDownLatch相反,CyclicBarrier設置一個屏障掠抬,當要求個數(shù)的線程到齊了才能執(zhí)行吼野,之前到的會一直阻塞在這。即允許一組線程互相等待两波,直到到達某個公共的屏障點(common barrier point)瞳步。
在涉及一組固定大小的線程的程序中,這些線程必須不時地互相等待雨女,此時CyclicBarrier很有用谚攒,因為該barrier在釋放等待線程后可以重用阳准,所以稱它為循環(huán)的barrier
問題五:CyclicBarrier的原理
原理:ReentrantLock 和 Condition 的組合使用
舉例:
問題六:CountDownLatch與CyclicBarrier的區(qū)別
1氛堕、CyclicBarrier的計數(shù)器由自己控制;而CountDownLatch的計數(shù)器則由使用者來控制
2野蝇、在CyclicBarrier中線程調用await方法不僅會將自己阻塞還會將計數(shù)器減1讼稚,而在CountDownLatch中線程調用await方法只是將自己阻塞而不會減少計數(shù)器的值。
3绕沈、CountDownLatch只能攔截一輪锐想,而CyclicBarrier可以實現(xiàn)循環(huán)攔截。一般來說用CyclicBarrier可以實現(xiàn)CountDownLatch的功能乍狐,而反之則不能赠摇。
三、Semaphore
信號量是一類經典的同步工具浅蚪。信號量通常用來限制線程可以同時訪問的(物理或邏輯)資源數(shù)量藕帜。
在資源有多個的時候,可以用Semaphore來進行同步惜傲。
問題六:Semaphore?的原理
原理:AQS中的Shared相關洽故,如tryAcquireShared()、tryReleaseShared()等方法盗誊。通過getState來判斷是否可以獲取資源
使用場景:比如說时甚,又到了十一假期,買票是重點哈踱,必須圈起來荒适。在購票大廳里,有5個售票窗口开镣,也就是說同一時刻可以服務5個人刀诬。要實現(xiàn)這種業(yè)務需求,用synchronized顯然不合適哑子。
查看Java并發(fā)工具舅列,發(fā)現(xiàn)有一個Semaphore類肌割,天生就是處理這種情況的。
舉例:
四帐要、Phaser
可重用的同步屏障把敞,類似CyclicBarrier和CountDownLatch,但使用上更為靈活
使用場景:非常適用于在多線程環(huán)境下同步協(xié)調分階段計算任務(Fork/join框架的子任務之間需同步時榨惠,優(yōu)先使用Phaser)
五奋早、Executors
提供了一系列工廠方法用于創(chuàng)建線程池(四種),返回的線程池都實現(xiàn)了ExecutorService接口赠橙。
六耽装、Exchanger
允許兩個線程在某個匯合點交換對象,在某些管道設計時比較有用期揪。
Exchanger提供了一個同步點掉奄,在這個同步點,一對線程可以交換數(shù)據(jù)凤薛。每個線程通過Exchanger()方法的入口提供數(shù)據(jù)給他的伙伴線程姓建,并接收他的伙伴線程提供的數(shù)據(jù)并返回。當兩個線程通過Exchaner交換了對象缤苫,這個交換對于兩個線程來說都是安全的速兔。
Exchanger可以認為是SynchronousQueue的雙向形式,在運用到遺傳算法和管道設計的應用中比較有用