JUC併發程式設計學習筆記(七)常用的輔助類

高同學,你好發表於2023-11-04

常用的輔助類

CountDownLatch

這是一個JUC計數器輔助類,計數器有加有減,這是減。

使用方法

package org.example.demo;

import java.util.concurrent.CountDownLatch;

//執行緒計數器
public class CountDownLatchDemo {
    public static void main(String[] args) {
        CountDownLatch countDownLatch = new CountDownLatch(6);//總數為6,必須要執行任務時用
        for (int i = 0; i < 6; i++) {
            new Thread(()->{
                System.out.println(Thread.currentThread().getName()+" go out");
                countDownLatch.countDown();//總數減1
            },String.valueOf(i)).start();
        }
        try {
            countDownLatch.await();//等待總數變為0才會往下執行,相當於阻塞當前執行緒
        } catch (InterruptedException e) {
            throw new RuntimeException(e);
        }
        System.out.println("關門");
    }
}

使用前

可能會在所有人沒出去之前關門

使用後

不在乎誰先出去,但是一定要總數等於0後才會關門

原理

countDownLatch.countDown();//總數減1

countDownLatch.await();//等待總數變為0才會往下執行,相當於阻塞當前執行緒

每次有執行緒呼叫countDown() 數量減一,假設計數器變為0,await()就會被喚醒,繼續執行!

CyclicBarrier

有減法就有加法

使用方法略有不同,一是新增了達到數量後可以執行一個方法,二十await方法放在了執行緒的內部

package org.example.demo;

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

public class CyclicBarrierDemo {
    public static void main(String[] args) {
        CyclicBarrier cyclicBarrier = new CyclicBarrier(7,()->{
            System.out.println("召喚神龍成功");//在達到數量後執行一個Runnable介面方法
        });

        for (int i = 1; i <= 7; i++) {
            //lambda表示式本質上還是new了一個類,所以無法直接拿到for迴圈中的變數i,需要透過一個臨時變數final來作為一箇中間變數來獲取到i
            final int temp = i;
            new Thread(()->{
                System.out.println(Thread.currentThread().getName()+":獲取到了"+temp+"顆龍珠");

                try {
                    cyclicBarrier.await();//每次等待完成後往下執行,如果達不到數量會死在這
                } catch (InterruptedException e) {
                    throw new RuntimeException(e);
                } catch (BrokenBarrierException e) {
                    throw new RuntimeException(e);
                }
            },String.valueOf(i)).start();
        }



    }
}
Semaphore

Semaphore:訊號量

搶車位:6輛車3個車位,123佔據了那麼456就需要等待,當佔據的車走後,那麼等待的車就要進入該車位。

用於限流等操作

package org.example.demo;

import java.sql.Time;
import java.util.concurrent.Semaphore;
import java.util.concurrent.TimeUnit;

public class SemaphoreDemo {
    public static void main(String[] args) {
//        執行緒數量:限流!讓沒有得到的等待釋放
        Semaphore sim = new Semaphore(3);
        for (int i = 0; i < 6; i++) {
            new Thread(()->{
                //acquire 得到
                //release 釋放
                try {
                    sim.acquire();
                    System.out.println(Thread.currentThread().getName()+":搶到車位");
                    TimeUnit.SECONDS.sleep(2);
                    System.out.println(Thread.currentThread().getName()+":離開車位");

                } catch (InterruptedException e) {
                    throw new RuntimeException(e);
                }finally {//所有需要關閉、釋放的操作都放在finally中
                    sim.release();
                }


            }).start();
        }
    }
}

sim.acquire();//得到

sim.release();//釋放

作用:多個共享資源互斥的使用!併發限流,控制最大執行緒數!

相關文章