JUC中T0級的三大輔助工具類(Semaphore,CountDownLatch,CyclicBarrier)

一、CountDownLatch(減少計數)讓一些線程阻塞直到另一些線程完成一系列操作後才被喚醒

主要有兩個方法,
1.1 當一個或多個線程調用await方法時,這些線程會阻塞,其它線程調用countDown方法會將計數器減一(調用countDown方法的線程不會阻塞);
1.2 當計數器的值變爲0時,await方法阻塞的線程會被喚醒,繼續執行

示例代碼:

import java.util.concurrent.CountDownLatch;

/**

 * 解釋:8個飯桶陸續離開食堂後掃地僧纔可以關燈
 *
 * main主線程必須要等前面8個線程完成全部工作後,自己才能開幹
 */
public class CountDownLatchDemo {
    public static void main(String[] args) throws InterruptedException {
        CountDownLatch countDownLatch = new CountDownLatch(6);
 		//8個在食堂的同學,各自離開食堂的時間不一致
        for (int i = 1; i <= 8; i++){
            new Thread(() -> {
                System.out.println(Thread.currentThread().getName() + "\t 號飯桶離開食堂");
                countDownLatch.countDown();
            }, String.valueOf(i)).start();
        }
        countDownLatch.await();
        System.out.println(Thread.currentThread().getName() + "\t****** 掃地僧關燈走人");

    }

}
二、CyclicBarrier(循環柵欄)可循環(Cyclic)使用的屏障(Barrier)

作用:讓一組線程到達一個屏障(也可以叫同步點)時被阻塞,直到最後一個線程到達屏障時,屏障纔會開門,所有被屏障攔截的線程纔會繼續幹活,線程進入屏障通過CyclicBarrier的await()方法

import java.util.concurrent.BrokenBarrierException;
import java.util.concurrent.CyclicBarrier;

/**
 * 
 * 集齊5福瓜分5億
 */
public class CyclicBarrierDemo {
    private static final int NUMBER = 7;

    public static void main(String[] args) {
        //CyclicBarrier(int parties, Runnable barrierAction)

        CyclicBarrier cyclicBarrier = new CyclicBarrier(NUMBER, () -> {
            System.out.println("*****集齊5福瓜分5億");
        });

        for (int i = 1; i <= 5; i++) {
            new Thread(() -> {
                try {
                    System.out.println(Thread.currentThread().getName() + "\t 張福被收集 ");
                    cyclicBarrier.await();
                } catch (InterruptedException | BrokenBarrierException e) {
                    e.printStackTrace();
                }

            }, String.valueOf(i)).start();
        }

    }
}
三、Semaphore(信號量)用於多個共享資源的互斥使和控制併發線程數

3.1 acquire(獲取) 當一個線程調用acquire操作時,它要麼通過成功獲取信號量(信號量減1),要麼一直等下去,直到有線程釋放信號量,或超時;
3.2 release(釋放)實際上會將信號量的值加1,然後喚醒等待的線程。

import java.util.Random;
import java.util.concurrent.Semaphore;
import java.util.concurrent.TimeUnit;

/**
 *
 *  廁所佔坑
 */
public class SemaphoreDemo {
    public static void main(String[] args) {
    	//設置5個坑位
        Semaphore semaphore = new Semaphore(5);
		//設置9個人拉屎
        for (int i = 1; i <= 9; i++) {
            new Thread(() -> {
                try {
                    semaphore.acquire();
                    System.out.println(Thread.currentThread().getName() + "\t 搶到了坑位");
                    TimeUnit.SECONDS.sleep(new Random().nextInt(5));
                    System.out.println(Thread.currentThread().getName() + "\t------- 離開");
                } catch (InterruptedException e) {
                    e.printStackTrace();
                } finally {
                    semaphore.release();
                }
            }, String.valueOf(i)).start();
        }
    }
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章