zoukankan      html  css  js  c++  java
  • java高级---->Thread之CountDownLatch的使用

      CountDownLatch是JDK 5+里面闭锁的一个实现,允许一个或者多个线程等待某个事件的发生。今天我们通过一些实例来学习一下它的用法。

    CountDownLatch的简单使用

     CountDownLatch的简单介绍:

    CountDownLatch类是一个同步计数器,构造时传入int参数,该参数就是计数器的初始值,每调用一次countDown()方法,计数器减1,计数器大于0 时,await()方法会阻塞程序继续执行
    CountDownLatch是一个倒计数的锁存器,当计数减至0时触发特定的事件。

    CountDownLatch被用来同步一个或多个任务,强制它们等待由其他任务执行的一组操作完成。你可以向CountDownLatch对象设置一个初始计数值,任何在这个对象上调用wait()方法都将阻塞,直至这个计数值达到0。其他任务在结束工作时,可以在该对象上调用凑你countDown()来减小这个计数值。CountDownLatch被设计为只触发一次,计数值不能被重置。如果你需要能够重置计数值的版本,则可以使用CyclicBarrier。

    以下是jdk文档上的两个例子,我们可以学习一下。

     一、开始信号,阻止任何工人进行,直到司机准备好他们继续进行

    package com.linux.huhx.concurreny;
    
    import java.util.concurrent.CountDownLatch;
    import java.util.concurrent.TimeUnit;
    
    public class Driver1 {
        public static void main(String[] args) throws Exception {
            CountDownLatch startSignal = new CountDownLatch(1);
            CountDownLatch doneSignal = new CountDownLatch(5);
            for (int i = 0; i < 5; ++i) // create and start threads
                new Thread(new TaskWorker(startSignal, doneSignal)).start();
            System.out.println("countDown before.");           // don't let run yet
            startSignal.countDown();      // let all threads proceed
            TimeUnit.SECONDS.sleep(1);
            System.out.println("await before");
            /**
             * 1、由于doneSignal里面的初始count=5,所以主线程在此会阻塞。
             * 2、当所有的子线程执行完(doneSignal.countDown())之后,此时的count=0。所以后面代码可以继续执行。
             */
            doneSignal.await();
            System.out.println("await after");
        }
    
        private static class TaskWorker implements Runnable {
            private final CountDownLatch startSignal;
            private final CountDownLatch doneSignal;
    
            public TaskWorker(CountDownLatch startSignal, CountDownLatch doneSignal) {
                this.startSignal = startSignal;
                this.doneSignal = doneSignal;
            }
    
            @Override
            public void run() {
                try {
                    /**
                     * 1、刚进来的时候,由于startSignal的count=1。所以await()方法阻塞于此。
                     * 2、当主线程执行了startSignal.countDown();此时的startSignal的count=0。所以子线程可以正常运行。
                     */
                    startSignal.await();
                    doSomeWork();
                    doneSignal.countDown();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
    
            private void doSomeWork() {
                System.out.println("in run method: " + Thread.currentThread().getName());
            }
        }
    }

    执行的结果如下:子线程的执行顺序不固定

    countDown before.
    in run method: Thread-0
    in run method: Thread-1
    in run method: Thread-2
    in run method: Thread-4
    in run method: Thread-3
    await before
    await after

    调用countDown()的任务在产生这个调用时并没有阻塞,只有对await()的调用会被阻塞,直至计数值到达0。

     二、完成信号,允许司机等到所有工人完成为止

    package com.linux.huhx.concurreny;
    
    import java.util.Random;
    import java.util.concurrent.CountDownLatch;
    import java.util.concurrent.ExecutorService;
    import java.util.concurrent.Executors;
    
    public class Driver2 {
        public static void main(String[] args) throws Exception {
            CountDownLatch doneSignal = new CountDownLatch(5);
            ExecutorService service = Executors.newFixedThreadPool(3);
            for (int i = 0; i < 5; ++i) // create and start threads
                service.execute(new WorkerRunnable(doneSignal, i));
            System.out.println("await before");
            doneSignal.await();
            System.out.println("await after");
            service.shutdown();
        }
    
        private static class WorkerRunnable implements Runnable {
            private final CountDownLatch doneSignal;
            private final int i;
    
            public WorkerRunnable(CountDownLatch doneSignal, int i) {
                this.doneSignal = doneSignal;
                this.i = i;
            }
    
            @Override
            public void run() {
                doWork(i);
                try {
                    Thread.sleep(new Random().nextInt(1000));
                    doneSignal.countDown();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
    
            private void doWork(int i) {
                System.out.println("in run method: " + i + " " + Thread.currentThread().getName());
            }
        }
    }

     运行的结果如下:子线程的执行顺序不固定

    await before
    in run method: 0 pool-1-thread-1
    in run method: 2 pool-1-thread-3
    in run method: 1 pool-1-thread-2
    in run method: 3 pool-1-thread-1
    in run method: 4 pool-1-thread-2
    await after

    友情链接

  • 相关阅读:
    php数组的创建及操作
    继承的几种方式
    js对象的创建与原型总结
    对象的创建
    变量与内存
    js函数的几个特殊点
    正则表达式的几个简单验证
    数组排序sort()
    对象与数组
    js函数动态传参
  • 原文地址:https://www.cnblogs.com/huhx/p/baseusejavaCountDownLatch.html
Copyright © 2011-2022 走看看