2.2線程的併發工具類-CountDownLatch、CyclicBarrier

一、CountDownLatch

1、作用

一組線程等待其他線程完成工作之後再執行,比較像加強版的join
下面演示下用法,5個線程6個扣除點,等待5個線程工作完成後,業務線程才進行自己的邏輯處理。

package cn.enjoy.controller.thread.CountDownLatch;

import cn.enjoy.controller.thread.DBPOLL.SleepTools;

import java.util.concurrent.CountDownLatch;

/**
 * @ author:wangle
 * @ description: countDownLatch的使用,6個初始化線程,6個扣除點,等待處理完之後業務線程和主線程才能進行處理自己的模塊
 * @ version:V1.0
 * @ date:2020-03-21 20:52
 **/
public class UseCountDownLatch {

    static CountDownLatch latch = new CountDownLatch(6);

    //初始化線程
    private static class InitThread implements Runnable{
        @Override
        public void run(){
            System.out.println("Thread:"+Thread.currentThread().getName()+"初始化工作");
            latch.countDown();
            //TODO 還可以繼續做其他業務
        }
    }

    //業務線程,扣除1次
    private static class BusinessThread implements Runnable{
        @Override
        public void run(){
            try{
                latch.await();
            }catch (InterruptedException e){
                e.printStackTrace();
            }
            System.out.println("Thread:"+Thread.currentThread().getName()+"業務線程執行了");
        }
    }


    //業務線程,扣除2次
    private static class BusinessThread2 extends Thread{

        @Override
        public void run(){
            SleepTools.ms(1);
            System.out.println("Thread:"+Thread.currentThread().getName()+"初始化工作1");
            latch.countDown();
            SleepTools.ms(1);
            System.out.println("Thread:"+Thread.currentThread().getName()+"初始化工作2");
            latch.countDown();
        }
    }



    public static void main(String[] args)throws InterruptedException{

        //業務線程開始執行
        new Thread(new BusinessThread()).start();

        //初始化線程執行
        for(int i=0;i<4;i++){
            Thread thread = new Thread(new InitThread());
            thread.start();
        }
        
        Thread thread = new BusinessThread2();
        thread.start();
        
        latch.await();
        System.out.println("主線程在執行了");
    }
}

在這裏插入圖片描述
看到,當5個線程扣除6次之後,主線程和業務線程纔開始執行,因爲主線程和業務線程執行了await操作,在等待初始化線程扣除操作完成。

二、CyclicBarrier

1、作用

一組線程到達了某個屏障,當這組線程全部到達了屏障點後全部線程才繼續向下執行

package cn.enjoy.controller.thread.UseCyclicBarrier;

import java.util.HashMap;
import java.util.Random;
import java.util.concurrent.CyclicBarrier;

/**
 * @author:wangle
 * @description:使用CyclicBarrier
 * @version:V1.0
 * @date:2020-03-21 21:28
 **/
public class UseCyclicBarrier {

    private static CyclicBarrier cyclicBarrier = new CyclicBarrier(5,new BusinessThread());
    private static HashMap<String,Long> threadIdMap = new HashMap<>();

    private static class WorkThread extends Thread{
        @Override
        public void run(){
            long id = Thread.currentThread().getId();
            threadIdMap.put(Thread.currentThread().getId()+"",id);
            Random r = new Random();
            try{
                if(r.nextBoolean()){
                    Thread.sleep(2000);
                    System.out.println("Thread_"+id+"還沒到await,在做其他事情");
                }
                System.out.println("Thread_"+id+"在await");
                cyclicBarrier.await();
                System.out.println("Thread_"+id+"業務代碼執行");
            }catch (Exception e){
                e.printStackTrace();
            }
        }
    }

    private static class BusinessThread extends Thread{
        @Override
        public void run(){
            System.out.println(threadIdMap);
        }
    }

    public static void main(String[] args){
        for(int i=0;i<5;i++){
            Thread thread = new WorkThread();
            thread.start();
        }
    }


}

在這裏插入圖片描述
可以看到,線程12,11很快到達了await,但是14,13,15還沒有到達await,,此時12,11並沒有進行繼續操作,而是等待剩餘的線程全部到達await之後才進行await之後的邏輯處理。有興趣的小夥伴可以執行下程序,明顯的感受下程序堵塞等待的順序。

CyclicBarrier還接收了一個線程的參數,這個線程也是當所有線程都到達了屏障之後才進行繼續操作。這個參數可有可無,根據自己的程序需要進行傳遞。

三、CountDownLatch和cyclicBarrier辨析

1、CountDownLatch放行由外部線程決定,cyclicBarrier放行是由一組線程本身決定的
2、CountDownLatch的放行條件執行數大於等於線程數、cyclicBarrier的放行條件執行數等於線程數量

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