Java併發工具類CountDownLatch和CyclicBarrier
Java併發工具類CountDownLatch和CyclicBarrier
1.CountDownLatch
CountDownLatch允許一個或多個線程等待其他線程完成操作,其構造函數接收一個int型的參數作爲計數器,若想等待N個點完成,就傳人N。此處的N個點,可指N個線程,也可以是1個線程中的N個步驟。
主要的方法爲CountDown()和await()。當調用CountDown()時,N會減1,await()方法會阻塞當前線程,直到N變爲零。
計數器必須大於等於0,只要等到0時候,調用await方法不會阻塞當前線程。CountDownLatch不可能重新初始化或者修改CountDownLatch對象內部的計數器值。一個線程調用countDown方法happen-before,另外一個線程調用await方法。
2.CyclicBarrier
CyclicBarrier讓一組線程到達一個屏障(或同步點)時被阻塞,直到最後一個線程到達屏障,屏障纔會被打開,所有被阻塞的線程纔會繼續執行。
CyclicBarrier默認的構造方法爲CyclicBarrier(int parties),其參數代表屏障被攔截的線程數,每個線程要調用CyclicBarrier對象的await方法,通知屏障線程已經到達同步點,然後該線程被阻塞。
CyclicBarrier的高級構造方法爲CyclicBarrier(intparties,Runnable barrierAction),用於在所有的線程都到達屏障時,優先執行barrierAction,然後執行被阻塞的線程。
CyclicBarrier可以應用於多線程計算數據,然後合併計算結果的場景。例如,用一個Excel保存了用戶所有的銀行流水,每個sheet保存一個賬戶近一年的每筆流水,現在需要統計用戶的日均流水,先用多線程處理每個sheet裏的銀行流水,都執行完之後,得到每個sheet的日均流水,最後,再用barrierAction用這些線程的計算結果,計算出整個Excel的日均銀行流水。
import java.util.concurrent.BrokenBarrierException;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.CyclicBarrier;
import java.util.concurrent.Executor;
import java.util.concurrent.Executors;
import java.util.Map.Entry;
public class BankWorkerService implements Runnable{
private CyclicBarrier c = new CyclicBarrier(4, this);
private Executor exe = Executors.newFixedThreadPool(4);
private ConcurrentHashMap<String,sheetBankWaterCount =
new ConcurrentHashMap<String, Integer>();
private void count() {
for (int i = 0; i < 4; i++) {
exe.execute(new Runnable() {
@Override
public void run() {
// TODO Auto-generated method stub
sheetBankWaterCount.put
(Thread.currentThread().getName(), 1);
try {
try {
c.await();
(Thread.currentThread().
getName());
} catch (BrokenBarrierException
e) {
e.printStackTrace();
}
}catch (InterruptedException e)
{
e.printStackTrace();
}
}
});
}
}
@Override
public void run() {
int result = 0;
for (Entry<String, Integer> sheet :
sheetBankWaterCount.entrySet()) {
result += sheet.getValue();
}
sheetBankWaterCount.put("result", result);
System.out.println(Thread.currentThread().
getName());
}
public static void main(String[] args) {
BankWorkerService bankWaterCount = new
BankWorkerService();
bankWaterCount.count();
}
}
● 1
●
輸出
4
pool-1-thread-4
pool-1-thread-4
pool-1-thread-1
pool-1-thread-2
pool-1-thread-3
●
3.CyclicBarrier和CountDownLatch的區別
CountDownLacth的計數器只能使用一次,
而CyclicBarrier的計數器可以使用reset方法重置。
所以CyclicBarrier能處理更爲複雜的業務場景。例如,
若計算髮生錯誤,可以重置計數器,並讓線程重新執行一次。
CyclicBarrier還提供其他有用的方法,比如getNumberWaiting方法可以獲得CyclicBarrier阻塞的線程數量。
isBroken()方法用來了解阻塞的線程是否被中斷。
1.CountDownLatch
CountDownLatch允許一個或多個線程等待其他線程完成操作,其構造函數接收一個int型的參數作爲計數器,若想等待N個點完成,就傳人N。此處的N個點,可指N個線程,也可以是1個線程中的N個步驟。
主要的方法爲CountDown()和await()。當調用CountDown()時,N會減1,await()方法會阻塞當前線程,直到N變爲零。
計數器必須大於等於0,只要等到0時候,調用await方法不會阻塞當前線程。CountDownLatch不可能重新初始化或者修改CountDownLatch對象內部的計數器值。一個線程調用countDown方法happen-before,另外一個線程調用await方法。
2.CyclicBarrier
CyclicBarrier讓一組線程到達一個屏障(或同步點)時被阻塞,直到最後一個線程到達屏障,屏障纔會被打開,所有被阻塞的線程纔會繼續執行。
CyclicBarrier默認的構造方法爲CyclicBarrier(int parties),其參數代表屏障被攔截的線程數,每個線程要調用CyclicBarrier對象的await方法,通知屏障線程已經到達同步點,然後該線程被阻塞。
CyclicBarrier的高級構造方法爲CyclicBarrier(intparties,Runnable barrierAction),用於在所有的線程都到達屏障時,優先執行barrierAction,然後執行被阻塞的線程。
CyclicBarrier可以應用於多線程計算數據,然後合併計算結果的場景。例如,用一個Excel保存了用戶所有的銀行流水,每個sheet保存一個賬戶近一年的每筆流水,現在需要統計用戶的日均流水,先用多線程處理每個sheet裏的銀行流水,都執行完之後,得到每個sheet的日均流水,最後,再用barrierAction用這些線程的計算結果,計算出整個Excel的日均銀行流水。
import java.util.concurrent.BrokenBarrierException;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.CyclicBarrier;
import java.util.concurrent.Executor;
import java.util.concurrent.Executors;
import java.util.Map.Entry;
public class BankWorkerService implements Runnable{
private CyclicBarrier c = new CyclicBarrier(4, this);
private Executor exe = Executors.newFixedThreadPool(4);
private ConcurrentHashMap<String,sheetBankWaterCount =
new ConcurrentHashMap<String, Integer>();
private void count() {
for (int i = 0; i < 4; i++) {
exe.execute(new Runnable() {
@Override
public void run() {
// TODO Auto-generated method stub
sheetBankWaterCount.put
(Thread.currentThread().getName(), 1);
try {
try {
c.await();
(Thread.currentThread().
getName());
} catch (BrokenBarrierException
e) {
e.printStackTrace();
}
}catch (InterruptedException e)
{
e.printStackTrace();
}
}
});
}
}
@Override
public void run() {
int result = 0;
for (Entry<String, Integer> sheet :
sheetBankWaterCount.entrySet()) {
result += sheet.getValue();
}
sheetBankWaterCount.put("result", result);
System.out.println(Thread.currentThread().
getName());
}
public static void main(String[] args) {
BankWorkerService bankWaterCount = new
BankWorkerService();
bankWaterCount.count();
}
}
● 1
●
輸出
4
pool-1-thread-4
pool-1-thread-4
pool-1-thread-1
pool-1-thread-2
pool-1-thread-3
●
3.CyclicBarrier和CountDownLatch的區別
CountDownLacth的計數器只能使用一次,
而CyclicBarrier的計數器可以使用reset方法重置。
所以CyclicBarrier能處理更爲複雜的業務場景。例如,
若計算髮生錯誤,可以重置計數器,並讓線程重新執行一次。
CyclicBarrier還提供其他有用的方法,比如getNumberWaiting方法可以獲得CyclicBarrier阻塞的線程數量。
isBroken()方法用來了解阻塞的線程是否被中斷。
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.