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(); } } }