Java併發工具類(1):CountDownLatch相關介紹

在多線程編程的時候,有時候需要控制併發流,Java本身提供了幾個控制併發的工具類,比如CountDownLatch,CyclicBarrier,Semaphore等。

1、CountDownLatch允許一個或者多個線程等等其他線程完成。

如果有個會議,等所有的人到了才能開始,假如每個人都是一個線程,開會需要等待每個線程結束。

CountDownLatch.countDown這個方法是CountDownLatch會把計數器的值減1,CountDownLatch.await等待計數器爲0時纔會執行下面的代碼。

package com.example.demo;

import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.atomic.AtomicInteger;

public class CountDownLatchTest {
    //10個線程的線程池
    ExecutorService executorService = Executors.newFixedThreadPool(10);
    CountDownLatch countDownLatch = new CountDownLatch(20);

    //計數器
    volatile AtomicInteger atomicInteger = new AtomicInteger(1);

    //等多有人到齊開會
    private  void meeting() throws InterruptedException{
        for(int i=1;i<=20;i++)
        {
            executorService.execute(()->{
                System.out.println("大家好,帥哥"+atomicInteger.getAndIncrement()+"報到!");
                countDownLatch.countDown();
            });
        }

        countDownLatch.await();
        executorService.shutdown();
        System.out.println("人已到齊,開始開會!");
    }

    public static void main(String[] args){
        CountDownLatchTest test = new CountDownLatchTest();
        try{
            test.meeting();
        }catch (InterruptedException e){

        }
    }

}

輸出結果如下,等所有的線程結束,纔會往下執行。

大家好,帥哥1報到!
大家好,帥哥2報到!
大家好,帥哥3報到!
大家好,帥哥4報到!
大家好,帥哥5報到!
大家好,帥哥6報到!
大家好,帥哥7報到!
大家好,帥哥8報到!
大家好,帥哥9報到!
大家好,帥哥10報到!
大家好,帥哥11報到!
大家好,帥哥12報到!
大家好,帥哥14報到!
大家好,帥哥13報到!
大家好,帥哥20報到!
大家好,帥哥19報到!
大家好,帥哥17報到!
大家好,帥哥18報到!
大家好,帥哥15報到!
大家好,帥哥16報到!
人已到齊,開始開會!

 

2、CountDownLatch 控制異步和同步

應用場景舉例:

  執行A項目的方法,需要調用B項目、C項目、D項目的接口方法。

需求:

  異步調用B、C、D項目的接口方法,且每個接口都調用結束後,A項目的方法纔可以結束。

注:如果需要獲取接口返回結果,可以使用緩存(key,value)保存。線程只支持線程外的靜態參數傳遞,不嚴謹。

public static void main(String[] args) throws InterruptedException {
        System.out.println("<=================A項目方法開始==============>");
        CountDownLatch latch = new CountDownLatch(3);
        Thread B = new Thread(new Runnable() {
            @Override
            public void run() {
                System.out.println("B項目接口調用===開始");
                try {
                    Thread.sleep(10000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                System.out.println("B項目接口調用===結束");
                latch.countDown();
            }
        });

        Thread C = new Thread(new Runnable() {
            @Override
            public void run() {
                System.out.println("C項目接口調用===開始");
                try {
                    Thread.sleep(5000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                System.out.println("C項目接口調用===結束");
                latch.countDown();
            }
        });

        Thread D = new Thread(new Runnable() {
            @Override
            public void run() {
                System.out.println("D項目接口調用===開始");
                try {
                    Thread.sleep(3000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                System.out.println("D項目接口調用===結束");
                latch.countDown();
            }
        });
        System.out.println("B C D start");
        B.start();
        C.start();
        D.start();
        latch.await();
        System.out.println("<=================A項目方法結束==============>");
    }

結果

<=================A項目方法開始==============>
B C D start
B項目接口調用===開始
C項目接口調用===開始
D項目接口調用===開始
D項目接口調用===結束
C項目接口調用===結束
B項目接口調用===結束
<=================A項目方法結束==============>

 

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