Java 併發編程學習筆記(8) ----CycliBarrier

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)

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章