天天看點

輔助類CountDownLatch, CyclicBarrier, SemaphoreCountDownLatch 減少計數CyclicBarrier 循環屏障Semaphore 信号量

文章目錄

  • CountDownLatch 減少計數
    • 場景
  • CyclicBarrier 循環屏障
    • 場景
  • Semaphore 信号量
    • 場景

JUC 中提供了三種常用的輔助類, 通過這些輔助類可以很好的解決線程數量過多時 Lock 鎖的頻繁操作

CountDownLatch 減少計數

  • CountDownLatch 類可以設定一個計數器, 然後通過 countDown 方法來進行減1 的操作
  • 使用await() 方法等待計數器為0, 然後繼續執行 await() 方法之後的語句
  • 當一個或多個線程調用 await() 方法時, 這些線程會阻塞
  • 其他線程調用 countDown 方法會将計數器減1(調用 countDown 方法的線程不會阻塞)
  • 當計數器的值變為 0 時, 因 await() 方法阻塞的線程會被喚醒, 繼續執行

場景

6個同學陸續離開教室後班長才可以關門

public static void main(String[] args) {
        CountDownLatch countDownLatch = new CountDownLatch(6);

        for (int i = 0; i < 6; i++) {
            new Thread(new Runnable() {
                @Override
                public void run() {
                    System.out.println(Thread.currentThread().getName()+ "同學離開教室");
                    countDownLatch.countDown();
                }
            },String.valueOf(i)).start();
        }

        try {
            countDownLatch.await();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println("班長鎖門啦!!!");
    }
           

CyclicBarrier 循環屏障

CyclicBarrier 的構造方法的第一個參數是目标障礙數, 每次執行 CyclicBarrier.await() 方法, 障礙數就會加1

如果達到了目标障礙數, 就執行給定的屏障動作, 由最後一個進入屏障的線程執行

場景

6個同學陸續離開教室後班長才可以關門

public static void main(String[] args) {
        CyclicBarrier cyclicBarrier = new CyclicBarrier(7, new Runnable() {
            @Override
            public void run() {
                System.out.println("班長鎖門啦!");
            }
        });

        for (int i = 0; i < 4; i++) {
            new Thread(new Runnable() {
                @Override
                public void run() {
                    try {
                        System.out.println(Thread.currentThread().getName() + " 同學離開教室了");
                        cyclicBarrier.await();
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    } catch (BrokenBarrierException e) {
                        e.printStackTrace();
                    }
                }
            },String.valueOf(i)).start();
        }
    }
           

Semaphore 信号量

  • Semaphore 的構造方法中傳入的第一個參數是最大信号量(可以看成是最大線程池)
  • 每個信号量隻能分發一個許可證
  • 使用 acquire() 方法獲得許可證, 使用 release() 方法釋放許可證

場景

搶車位, 6輛汽車, 3個停車位

public static void main(String[] args) {
        Semaphore semaphore = new Semaphore(3);

        for (int i = 0; i < 6; i++) {
            new Thread(new Runnable() {
                @Override
                public void run() {
                    try {
                        semaphore.acquire();
                        System.out.println(Thread.currentThread().getName() + " 搶到了停車位");
                        Thread.sleep(3000);
                        System.out.println(Thread.currentThread().getName() + " --------釋放了停車位");
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }finally {
                        semaphore.release();
                    }
                }
            },String.valueOf(i)).start();
        }
    }