zoukankan      html  css  js  c++  java
  • Java并发之CountDownLatch

    CountDownLatch是Java concurrent包下的一个同步工具。它可以让一个(或多个)线程等待,直到其他线程中的某些操作完成。

    本质上是一个信号量,我们把它比作一个有N个插销的大门,它把等待(调用await)的线程挡住了, 直到其他线程把插销去完了(调用countDown减到0),这批线程才能执行。

    下面是根据oracle官方文档改的一个例子:

    /**
     * 
     * Sample usage: Here is a pair of classes in which a group of worker threads use two countdown latches:
    
     The first is a start signal that prevents any worker from proceeding until the driver is ready for them to proceed;
     The second is a completion signal that allows the driver to wait until all workers have completed.
     */
    public class CountDownLatchDemo {
    
        public static void main(String[] args) throws InterruptedException {
            new Driver().run();
        }
    }
    
    class Driver {
        static final int N = 5;
        public void run() throws InterruptedException {
            CountDownLatch startSignal = new CountDownLatch(1);
    
            CountDownLatch doneSignal = new CountDownLatch(N);
            for (int i=0; i<N; i++) {
                new Thread(new Worker(startSignal, doneSignal))
                        .start();
            }
            doSomething(); // don't let run yet
            startSignal.countDown(); // let all threads proceed
            doneSignal.await(); // wait for all to finish
            doSomething();
        }
    
        private void doSomething() {
            System.out.println("doSomething");
        }
    }
    
    
    
    class Worker implements Runnable {
        private CountDownLatch startSignal;
        private CountDownLatch doneSignal;
    
        public Worker(CountDownLatch startSignal, CountDownLatch doneSignal) {
            this.startSignal = startSignal;
            this.doneSignal = doneSignal;
        }
    
        public void run() {
            try {
                startSignal.await();
                doWork();
                doneSignal.countDown();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    
        private void doWork() {
            System.out.println("worker work.");
        }
    }

    把Driver看作是一个监工,Worker看作是工人,有5个。

    • 监工发号施令后,工人们才可以干活。所以工人干活前调用startSignal.await(), 直到监工调用startSignal.countDown() 后Worker后续doWork才开始执行。 
    • 工人们干完活后通知监工,监工才可以接着发号。所以监工调用doneSignal.await()在哪儿等着,直到工人们都干完活(调用5次doneSignal.countDown())后,才能接着执行。

    看下执行结果,有助于理解整个工作过程和latch机制:

    doSomething
    worker work.
    worker work.
    worker work.
    worker work.
    worker work.
    doSomething

  • 相关阅读:
    单例模式中的懒汉式以及线程安全性问题
    单例模式中的饿汉模式
    自我管理的8个好习惯
    从java字节码角度看线程安全性问题
    工作上的建议
    从线程的优先级看饥饿问题
    多线程存在哪些风险
    DirectX SDK (June 2010)安装错误S1023,解决方法
    Microsoft DirectX SDK 2010 版本下载
    如果程序集是从 Web 上下载的,即使它存储于本地计算机,Windows 也会将其标记为 Web 文件,http://go.microsoft.com/fwlink/?LinkId=179545
  • 原文地址:https://www.cnblogs.com/dreamysmurf/p/6119730.html
Copyright © 2011-2022 走看看