1. 程式人生 > 其它 >ava併發程式設計之併發工具類CountDownLatch,CyclicBarrier,Semaphore詳解(轉)

ava併發程式設計之併發工具類CountDownLatch,CyclicBarrier,Semaphore詳解(轉)

1 前言

在JDK的併發包裡提供了幾個非常有用的併發工具類。CountDownLatch、CyclicBarrier和 Semaphore工具類提供了一種併發流程控制的手段,Exchanger工具類則提供了線上程間交換數 據的一種手段。本文會對這些併發工具類進行介紹。

2 等待多執行緒完成的CountDownLatch

2.1 CountDownLatch案例演示

countdownlatch 是一個同步工具類,它允許一個或多個執行緒一直等待,直到其他執行緒的操作執行完畢再執行。從命名可以解讀到 countdown 是倒數的意思,類似於我們倒計時的概念。
countdownlatch 提供了兩個方法,一個是 countDown,一個是 await,countdownlatch 初始化的時候需要傳入一個整數,在這個整數倒數到 0 之前,呼叫了 await 方法的程式都必須要等待,然後通過 countDown 來倒數。

public class CountDownLatchDemo {
    public static void main(String[] args) {
        CountDownLatch countDownLatch = new CountDownLatch(6);
        for (int i = 0; i < 6; i++) {
            new Thread(() -> {
                System.out.println(Thread.currentThread().getName()+"同學離開了");
                countDownLatch.countDown();
            }).start();
        }
        
try { countDownLatch.await(); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println(Thread.currentThread().getName()+"要關門了,此時教室已經沒人了~"); } }

3 同步屏障CyclicBarrier

CyclicBarrier的字面意思是可迴圈使用(Cyclic)的屏障(Barrier)。它要做的事情是,讓一 組執行緒到達一個屏障(也可以叫同步點)時被阻塞,直到最後一個執行緒到達屏障時,屏障才會 開門,所有被屏障攔截的執行緒才會繼續執行。

3.1 CyclicBarrier使用場景

使用場景:5個工程師一起來公司應聘,招聘方式分為筆試和麵試。首先,要等人到齊後,開始筆試;筆試結束之後,再一起參加面試。把5個人看作5個執行緒,程式碼如下:
Main類


public class Main {
    public static void main(String[] args) throws BrokenBarrierException, InterruptedException {
        CyclicBarrier barrier = new CyclicBarrier(5);
        for (int i = 0; i < 5; i++) {
            new MyThread("執行緒-" + (i + 1), barrier).start();
        }
    }
}

MyThread類:

public class MyThread extends Thread{

    private final CyclicBarrier barrier;
    private final Random random = new Random();
    public MyThread(String name, CyclicBarrier barrier) {
        super(name);
        this.barrier = barrier;
    }
    @Override public void run() {
        try {
            Thread.sleep(random.nextInt(2000));
            System.out.println(Thread.currentThread().getName() + " - 已經到達公司");
            barrier.await();
            Thread.sleep(random.nextInt(2000));
            System.out.println(Thread.currentThread().getName() + " - 已經筆試結束");
            barrier.await();
            Thread.sleep(random.nextInt(2000));
            System.out.println(Thread.currentThread().getName() + " - 已經面試結束");
        } catch (InterruptedException e) {
            e.printStackTrace();
        } catch (BrokenBarrierException e) {
            e.printStackTrace();
        }
        super.run();
    }
}

在整個過程中,有2個同步點:第1個同步點,要等所有應聘者都到達公司,再一起開始筆試;第2個同步點,要等所有應聘者都結束筆試,之後一起進入面試環節。

3.3 CyclicBarrier與CountDownLatch 區別

CountDownLatch 是一次性的,CyclicBarrier 是可迴圈利用的
CountDownLatch的計數器只能使用一次,而CyclicBarrier的計數器可以使用reset()方法重置,可以使用多次,所以CyclicBarrier能夠處理更為複雜的場景;

4 控制併發執行緒數的Semaphore

Semaphore(訊號量)是用來控制同時訪問特定資源的執行緒數量,它通過協調各個執行緒,以 保證合理的使用公共資源

4.1 Semaphore的使用場景

public class SemaphoreDemo {
    public static void main(String[] args) {
        Semaphore semaphore=new Semaphore(3);//此時海底撈有3個空桌
        for (int i = 0; i < 6; i++) {
            new Thread(() -> {
                try {
                    semaphore.acquire();
                    System.out.println("第"+Thread.currentThread().getName()+"等待者搶到座位。");
                    //假設每桌客人吃飯時間為3S
                    TimeUnit.SECONDS.sleep(3);
                    System.out.println("第"+Thread.currentThread().getName()+"客人吃完飯離開。");
                } catch (InterruptedException e) {
                    e.printStackTrace();
                } finally {
                    semaphore.release();
                }
            },String.valueOf(i)).start();
        }
    }
}



作者:幹天慈雨
連結:https://www.jianshu.com/p/6251c13bbb2e
來源:簡書
著作權歸作者所有。商業轉載請聯絡作者獲得授權,非商業轉載請註明出處。