java基础----CountDownLatch、CyclicBarrier

  CountDownLatch是juc包里面的一个计数器,用户可以为他设置一个初始值,并调用他的await()方法使当前线程转变为阻塞状态,直到CountDownLatch计数完毕。

  Enum是java中的枚举,当程序运行过程中需要根据一定的对应关系去获取一些数据的时候,通过数据库去拿这些数据是非常消耗性能的,因为中间有创建和销毁数据库连接的消耗,因此,可以用枚举来实现这些功能。

  下面通过一个例子来理解这两个东西

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

public class CountDownLatchDemo {
    public static void main(String[] args) throws InterruptedException {
        CountDownLatch countDownLatch = new CountDownLatch(6);
        Random rd = new Random();

        System.out.println(Thread.currentThread().getName() + "线程开始");
        for(int i = 0; i < 6; i++)
        {
            new Thread(()->{
                try {
                    System.out.println(Thread.currentThread().getName() + "线程开始");
                    TimeUnit.SECONDS.sleep(rd.nextInt(5));
                    System.out.println(Thread.currentThread().getName() + "线程结束");
                    countDownLatch.countDown();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            },ThreadEnum.getThreadNameByKey(i).getRetMessage()).start();
        }

        countDownLatch.await();
        System.out.println(Thread.currentThread().getName() + "线程结束");
    }
}

  在上述代码中,我们希望main线程在所有子线程都结束后才结束,因此在main线程中加入了countDownLatch.awati()方法,而每个子线程结束的时候,都会让countDownLatch -  1。值得一提的是,在获取线程名的时候,代码里面使用了枚举的方式去获取,ThreadEnum.getThreadNameByKey(i).getRetMessage()。枚举具体的代码如下:

import jdk.nashorn.internal.objects.annotations.Getter;

public enum ThreadEnum {
    ONE(0,"a"),
    TWO(1,"b"),
    THREE(2,"c"),
    FOUR(3,"d"),
    FIVE(4,"e"),
    SIX(5,"f");

    private Integer retCode;
    private String retMessage;

    public Integer getRetCode() {
        return retCode;
    }

    public void setRetCode(Integer retCode) {
        this.retCode = retCode;
    }

    public String getRetMessage() {
        return retMessage;
    }

    public void setRetMessage(String retMessage) {
        this.retMessage = retMessage;
    }

    ThreadEnum(Integer retCode, String retMessage)
    {
        this.retCode = retCode;
        this.retMessage = retMessage;
    }

    public static ThreadEnum getThreadNameByKey(int index)
    {
        ThreadEnum[] myArray = ThreadEnum.values();
        for(ThreadEnum element : myArray) {
            if(index == element.getRetCode())
            {
                return element;
            }
        }
        return null;
    }
}

  

  CyclicBarrier与CountDownLatch不同,如果说CountDownLatch相当于在做一个减法操作的话,那么CyclicBarrier就是在做一个加法操作,CyclicBarrier中会设置一个parties和一个runnabled,parties代表着需要多少个线程进来之后,才会执行runnabled里面的逻辑。而每个线程调用CyclicBarrier中的await方法后,就会进入到CyclicBarrier的计数当中,并切换到阻塞状态,直到指定数量的线程都进来CyclicBarrier后,屏障解除,各线程继续执行,同时运行CyclicBarrier中runnabled中的逻辑。

  如下列代码

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

public class CydicBarrierDemo {
    public static void main(String[] args) {
        Random rd = new Random();
        CyclicBarrier cyclicBarrier = new CyclicBarrier(7,()->{
            System.out.println("终极任务开始");
        });

        for(int i = 0; i < 7; i ++)
        {
            new Thread(()->{
                try {
                    System.out.println(Thread.currentThread().getName() + "\t线程启动了");
                    TimeUnit.SECONDS.sleep(rd.nextInt(5));
                    System.out.println(Thread.currentThread().getName() + "\t线程变为阻塞状态了");
                    cyclicBarrier.await();
                    System.out.println(Thread.currentThread().getName() + "\t线程重新运行了");
                } catch (InterruptedException e) {
                    e.printStackTrace();
                } catch (BrokenBarrierException e) {
                    e.printStackTrace();
                }
            },"t"+i).start();
        }
    }
}

    

posted @ 2020-09-11 15:38  喜欢it的小聪聪  阅读(105)  评论(0编辑  收藏  举报