CyclicBarrier 的使用
1.介紹
可以實現屏障等待的功能(階段性同步),同時可以循環實現要一起做任務的目標。
CyclicBarrier是一個同步輔助類,它允許一組線程互相等待,直到某個公告屏障點,這些線程必須相互等待。
2.CyclicBarrier 和 CountDownLatch 的區別:
CountDownLatch:一個或多個線程,等待另外一個或多個線程完成某個事情之後才能繼續執行。
CyclicBarrier:多個線程時間相互等待,任何一個線程完成之前,所有的線程都必須等待。
3.實現階段跑步比賽
代碼
package com.lhc.concurrent.cyclicBarrier;
import java.util.concurrent.BrokenBarrierException;
import java.util.concurrent.CyclicBarrier;
public class GameService {
private CyclicBarrier cyclicBarrier;
public GameService(CyclicBarrier cyclicBarrier) {
this.cyclicBarrier = cyclicBarrier;
}
public void game() {
try {
Thread.sleep((int) (Math.random() * 10000));
System.out.println(Thread.currentThread().getName() + " " + System.currentTimeMillis() +
"開始跑第1階段 " + (cyclicBarrier.getNumberWaiting() + 1));
cyclicBarrier.await();
System.out.println(Thread.currentThread().getName() + " " + System.currentTimeMillis() +
"結束跑第1階段 " + (cyclicBarrier.getNumberWaiting()));
Thread.sleep((int) (Math.random() * 10000));
System.out.println(Thread.currentThread().getName() + " " + System.currentTimeMillis() +
"開始跑第2階段 " + (cyclicBarrier.getNumberWaiting() + 1));
cyclicBarrier.await();
System.out.println(Thread.currentThread().getName() + " " + System.currentTimeMillis() +
"結束跑第2階段 " + (cyclicBarrier.getNumberWaiting()));
System.out.println();
} catch (InterruptedException e) {
e.printStackTrace();
} catch (BrokenBarrierException b) {
b.printStackTrace();
}
}
}
測試類
package com.lhc.concurrent.cyclicBarrier;
import java.util.concurrent.CyclicBarrier;
public class GameThread extends Thread {
private GameService gameService;
public GameThread(GameService gameService) {
this.gameService = gameService;
}
@Override
public void run() {
gameService.game();
}
public static void main(String[] args) {
CyclicBarrier cyclicBarrier = new CyclicBarrier(2);
GameService gameService = new GameService(cyclicBarrier);
GameThread gameThread0 = new GameThread(gameService);
gameThread0.setName("Thread0");
gameThread0.start();
GameThread gameThread1 = new GameThread(gameService);
gameThread1.setName("Thread1");
gameThread1.start();
GameThread gameThread2 = new GameThread(gameService);
gameThread2.setName("Thread2");
gameThread2.start();
GameThread gameThread3 = new GameThread(gameService);
gameThread3.setName("Thread3");
gameThread3.start();
}
}
打印結果
Thread1 1555921960659開始跑第1階段 1
Thread2 1555921964154開始跑第1階段 2
Thread2 1555921964154結束跑第1階段 0
Thread1 1555921964154結束跑第1階段 0
Thread0 1555921964821開始跑第1階段 1
Thread2 1555921967049開始跑第2階段 2
Thread2 1555921967049結束跑第2階段 0
Thread0 1555921967049結束跑第1階段 0
Thread3 1555921968773開始跑第1階段 1
Thread1 1555921973957開始跑第2階段 2
Thread1 1555921973957結束跑第2階段 0
Thread3 1555921973957結束跑第1階段 0
Thread0 1555921976853開始跑第2階段 1
Thread3 1555921977629開始跑第2階段 2
Thread3 1555921977629結束跑第2階段 0
Thread0 1555921977629結束跑第2階段 0
4.getNumberWaiting() 和 getParties()
getNumberWaiting() 獲取到達屏障點的線程
getParties() 取得parties個數
代碼
package com.lhc.concurrent.cyclicBarrier;
import java.util.concurrent.BrokenBarrierException;
import java.util.concurrent.CyclicBarrier;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;
public class PartyService {
public CyclicBarrier cyclicBarrier = new CyclicBarrier(3, new Runnable() {
@Override
public void run() {
System.out.println("徹底結束 " + System.currentTimeMillis());
}
});
public void doService() {
try {
System.out.println(Thread.currentThread().getName() + "準備");
if ("1".equals(Thread.currentThread().getName())) {
Thread.sleep(Integer.MAX_VALUE);
}
//等待指定時間,如果超時就拋出異常
cyclicBarrier.await(4, TimeUnit.SECONDS);
System.out.println(Thread.currentThread().getName() + "結束");
} catch (InterruptedException e) {
e.printStackTrace();
} catch (BrokenBarrierException e) {
e.printStackTrace();
}catch (TimeoutException e){
e.printStackTrace();
}
}
}
測試類
package com.lhc.concurrent.cyclicBarrier;
public class PartyThread extends Thread {
private PartyService partyService;
public PartyThread(PartyService partyService) {
super();
this.partyService = partyService;
}
@Override
public void run() {
partyService.doService();
}
public static void main(String[] args) {
PartyService partyService = new PartyService();
PartyThread[] partyThreads = new PartyThread[3];
for (int i = 0; i < partyThreads.length; i++) {
partyThreads[i] = new PartyThread(partyService);
partyThreads[i].setName(i + "");
partyThreads[i].start();
}
try{
Thread.sleep(1000);
}catch (InterruptedException e){
e.printStackTrace();
}
System.out.println("使用數" + partyService.cyclicBarrier.getParties());
System.out.println("等待數" + partyService.cyclicBarrier.getNumberWaiting());
}
}
打印結果
0準備
2準備
1準備
使用數3
等待數2
java.util.concurrent.BrokenBarrierException
at java.util.concurrent.CyclicBarrier.dowait(CyclicBarrier.java:250)
at java.util.concurrent.CyclicBarrier.await(CyclicBarrier.java:435)
at com.lhc.concurrent.cyclicBarrier.PartyService.doService(PartyService.java:22)
at com.lhc.concurrent.cyclicBarrier.PartyThread.run(PartyThread.java:13)
java.util.concurrent.TimeoutException
at java.util.concurrent.CyclicBarrier.dowait(CyclicBarrier.java:257)
at java.util.concurrent.CyclicBarrier.await(CyclicBarrier.java:435)
at com.lhc.concurrent.cyclicBarrier.PartyService.doService(PartyService.java:22)
at com.lhc.concurrent.cyclicBarrier.PartyThread.run(PartyThread.java:13)