首页 > 技术文章 > java并发之同步辅助类CountDownLatch

happyhuangjinjin 2018-03-16 22:14 原文

CountDownLatch

含义:

CountDownLatch可以理解为一个计数器在初始化时设置初始值,当一个线程需要等待某些操作先完成时,需要调用await()方法。这个方法让线程进入休眠状态直到等待的所有线程都执行完成。每调用一次countDown()方法内部计数器减1,直到计数器为0时唤醒。这个可以理解为特殊的CyclicBarrier。线程同步点比较特殊,为内部计数器值为0时开始。

 

方法:

核心方法两个:countDown()和await()

countDown():使CountDownLatch维护的内部计数器减1,每个被等待的线程完成的时候调用

await():线程在执行到CountDownLatch的时候会将此线程置于休眠

 

例子

开会的例子:会议室里等与会人员到齐了会议才能开始。

import java.util.concurrent.CountDownLatch;

 

public class VideoConference implements Runnable {

private final CountDownLatch controller;

 

public VideoConference(int number) {

controller = new CountDownLatch(number);

}

 

public void arrive(String name) {

System.out.printf("%s has arrived.\n", name);

 

controller.countDown();// 调用countDown()方法,使内部计数器减1

System.out.printf("VideoConference: Waiting for %d participants.\n", controller.getCount());

}

 

@Override

public void run() {

System.out.printf("VideoConference: Initialization: %d participants.\n", controller.getCount());

try {

 

controller.await();// 等待,直到CoutDownLatch计数器为0

 

System.out.printf("VideoConference: All the participants have come\n");

System.out.printf("VideoConference: Let's start...\n");

} catch (InterruptedException e) {

e.printStackTrace();

}

}

}

 

参加会议人员类

import java.util.concurrent.Semaphore;

import java.util.concurrent.TimeUnit;

import java.util.concurrent.locks.Lock;

import java.util.concurrent.locks.ReentrantLock;

 

public class PrintQueue {

//信号量

    private Semaphore semaphore;

    

    //是否空闲打印机

    private boolean freePrinters[];

    

    private Lock lockPrinters;

    

    public PrintQueue(){

     //初始化三个信号

        semaphore=new Semaphore(3);

        //三台空闲打印机

        freePrinters=new boolean[3];

        for (int i=0; i<3; i++){

            freePrinters[i]=true;

        }

        lockPrinters=new ReentrantLock();

    }

    

    public void printJob (Object document){

        try {

         //获取信号量

            semaphore.acquire();

            

            int assignedPrinter=getPrinter();

            

            Long duration=(long)(Math.random()*10);

            System.out.printf("%s: PrintQueue: Printing a Job in Printer %d during %d seconds\n",Thread.currentThread().getName(),assignedPrinter,duration);

            TimeUnit.SECONDS.sleep(duration);

            

            freePrinters[assignedPrinter]=true;

        } catch (InterruptedException e) {

            e.printStackTrace();

        } finally {

            // Free the semaphore

            semaphore.release();            

        }

    }

    private int getPrinter() {

        int ret=-1;

        

        try {

            lockPrinters.lock();

            for (int i=0; i<freePrinters.length; i++) {

                if (freePrinters[i]){

                    ret=i;

                    freePrinters[i]=false;

                    break;

                }

            }

        } catch (Exception e) {

            e.printStackTrace();

        } finally {

            lockPrinters.unlock();

        }

        return ret;

    }

}



 

测试类:

 

public class CountDownLatchMain {

 

public static void main(String[] args) {

VideoConference conference = new VideoConference(10);

Thread threadConference = new Thread(conference);

threadConference.start();// 开启await()方法,在内部计数器为0之前线程处于等待状态

for (int i = 0; i < 10; i++) {

Participant p = new Participant(conference, "Participant " + i);

Thread t = new Thread(p);

t.start();

}

}

 

}

海量视频获取 springboot springcloud

推荐阅读