zoukankan      html  css  js  c++  java
  • CountDownLatch——闭锁的实现之一

    CountDownLatch实际上是一种闭锁实现。闭锁:是一种同步工具类,可以延迟线程的进度直到其到达终止状态——《Java并发编程实战》。这个怎么解释呢?简单来说,就是有1个线程需要等待其余10个线程都执行完毕后再执行,这个时候就可以使用闭锁,也即CountDownLatch(当然闭锁的实现并不止这一种)。关于对闭锁的详细解释请参考《Java并发编程实战》P79。

    CountDownLatch中有一个计数器,该计数器通过构造方法传递,表示需要完成的工作。有两个主要的方法:countDown——表示计数器减1,再完成一个工作时调用此方法。await——表示唤醒,等待线程在执行方法前调用此方法,当计数器未为0(即还有工作尚未完成)时,被阻塞,当所有工作都已完成,计数器被减至0,此时等待线程才被唤醒以继续执行。

    我们通过代码来实际感受一下CountDownLatch类API的使用。

    首先有一个TaskThread任务线程,表示做好准备工作的线程。

     1 package countdownlatch;
     2 
     3 import java.util.concurrent.CountDownLatch;
     4 
     5 /**
     6  * Created by yulinfeng on 12/14/16.
     7  */
     8 public class TaskThread implements Runnable {
     9     private final CountDownLatch latch;
    10 
    11     public TaskThread(CountDownLatch latch){
    12         this.latch = latch;
    13     }
    14 
    15     @Override
    16     public void run() {
    17         try {
    18             doWork();
    19             latch.countDown();  //线程执行完这部分工作后,CountDownLatch的计数减1。
    20         } catch (InterruptedException e) {
    21             e.printStackTrace();
    22         }
    23     }
    24 
    25     private void doWork() throws InterruptedException{
    26         System.out.println(Thread.currentThread().getName());
    27         Thread.sleep(2000);  //休眠2s,模拟这部分工作的完成
    28     }
    29 }

    接着是等待线程,即当所有的TaskThread完成各自的工作之后再执行此线程。

     1 package countdownlatch;
     2 
     3 import java.util.concurrent.CountDownLatch;
     4 
     5 /**
     6  * Created by yulinfeng on 12/14/16.
     7  */
     8 public class WaitThread implements Runnable{
     9     private final CountDownLatch latch;
    10 
    11     public WaitThread(CountDownLatch latch){
    12         this.latch = latch;
    13     }
    14 
    15     @Override
    16     public void run() {
    17         try {
    18             System.out.println("Wait for other threads to execute!");   //就算CPU在未完成所有TaskThread进入到次线程,该线程也会因为CountDownLatch计数器未减至0而阻塞。
    19             latch.await();  //直到CountDownLatch的计数器减至0(即表示所有的工作也完成)才继续执行,否则阻塞。
    20             System.out.println("Other threads have already completed!");
    21         } catch (InterruptedException e) {
    22             e.printStackTrace();
    23         }
    24 
    25     }
    26 }

    测试代码:

     1 package countdownlatch;
     2 
     3 import java.util.concurrent.CountDownLatch;
     4 import java.util.concurrent.ExecutorService;
     5 import java.util.concurrent.Executors;
     6 
     7 /**
     8  * Created by yulinfeng on 12/14/16.
     9  */
    10 public class Test {
    11 
    12     public static void main(String[] args){
    13         ExecutorService exec = Executors.newCachedThreadPool();
    14         CountDownLatch latch = new CountDownLatch(100);     //所有线程必须共享一个CountDownLatch单例(这也是在另外两个线程中CountDownLatch定义为final不可变引用的原因),模拟有100个工作待完成。
    15 
    16         exec.execute(new WaitThread(latch));    //等待线程
    17         for (int i = 0; i < 100; i++){
    18             exec.execute(new TaskThread(latch));    //开启100个线程,模拟完成100个工作。
    19         }
    20 
    21         exec.shutdown();
    22     }
    23 }

    执行结果很好的诠释了CountDownLatch:

  • 相关阅读:
    linux下inotifytools+rsync进行文件同步的使用
    进程间的通讯(IPC)方式
    is_writable的php实现
    PHP IPC函数介绍消息队列
    PHP实现多进程并行执行脚本
    PHP IPC函数介绍共享内存
    不同语言从shell管道获取数据的方法
    解决phpredis 'RedisException' with message 'read error on connection'
    beanstalkd的安装
    haproxy对redis进行负载均衡
  • 原文地址:https://www.cnblogs.com/yulinfeng/p/6181664.html
Copyright © 2011-2022 走看看