`
vvggsky
  • 浏览: 65646 次
  • 性别: Icon_minigender_1
  • 来自: 上海
社区版块
存档分类
最新评论

CountDownLatch join 或 CountDownLatch 让主线程等待所有子线程完成

阅读更多
用给定的计数 初始化 CountDownLatch。由于调用了 countDown() 方法,所以在当前计数到达零之前,await 方法会一直受阻塞。之后,会释放所有等待的线程,await 的所有后续调用都将立即返回。这种现象只出现一次——计数无法被重置。如果需要重置计数,请考虑使用 CyclicBarrier。

CountDownLatch 是一个通用同步工具,它有很多用途。将计数 1 初始化的 CountDownLatch 用作一个简单的开/关锁存器,或入口:在通过调用 countDown() 的线程打开入口前,所有调用 await 的线程都一直在入口处等待。用 N 初始化的 CountDownLatch 可以使一个线程在 N 个线程完成某项操作之前一直等待,或者使其在某项操作完成 N 次之前一直等待。

CountDownLatch 的一个有用特性是,它不要求调用 countDown 方法的线程等到计数到达零时才继续,而在所有线程都能通过之前,它只是阻止任何线程继续通过一个 await。

示例用法: 下面给出了两个类,其中一组 worker 线程使用了两个倒计数锁存器:

第一个类是一个启动信号,在 driver 为继续执行 worker 做好准备之前,它会阻止所有的 worker 继续执行。
第二个类是一个完成信号,它允许 driver 在完成所有 worker 之前一直等待。
class Driver { // ...
   void main() throws InterruptedException {
     CountDownLatch startSignal = new CountDownLatch(1);
     CountDownLatch doneSignal = new CountDownLatch(N);

     for (int i = 0; i < N; ++i) // create and start threads
       new Thread(new Worker(startSignal, doneSignal)).start();

     doSomethingElse();            // don't let run yet
     startSignal.countDown();      // let all threads proceed
     doSomethingElse();
     doneSignal.await();           // wait for all to finish
   }
 }

 class Worker implements Runnable {
   private final CountDownLatch startSignal;
   private final CountDownLatch doneSignal;
   Worker(CountDownLatch startSignal, CountDownLatch doneSignal) {
      this.startSignal = startSignal;
      this.doneSignal = doneSignal;
   }
   public void run() {
      try {
        startSignal.await();
        doWork();
        doneSignal.countDown();
} catch (InterruptedException ex) {} // return;
   }

   void doWork() { ... }
 }


另一种典型用法是,将一个问题分成 N 个部分,用执行每个部分并让锁存器倒计数的 Runnable 来描述每个部分,然后将所有 Runnable 加入到 Executor 队列。当所有的子部分完成后,协调线程就能够通过 await。(当线程必须用这种方法反复倒计数时,可改为使用 CyclicBarrier。)
 class Driver2 { // ...
   void main() throws InterruptedException {
     CountDownLatch doneSignal = new CountDownLatch(N);
     Executor e = ...

     for (int i = 0; i < N; ++i) // create and start threads
       e.execute(new WorkerRunnable(doneSignal, i));

     doneSignal.await();           // wait for all to finish
   }
 }

 class WorkerRunnable implements Runnable {
   private final CountDownLatch doneSignal;
   private final int i;
   WorkerRunnable(CountDownLatch doneSignal, int i) {
      this.doneSignal = doneSignal;
      this.i = i;
   }
   public void run() {
      try {
        doWork(i);
        doneSignal.countDown();
      } catch (InterruptedException ex) {} // return;
   }

   void doWork() { ... }
 }



public class WaitAllSubThread {   
  
    /*int liveThreadNum;//记录运行的子线程数  
    */  
    int n;  //工作线程数   
  
    public WaitAllSubThread(int n) {   
        this.n = n;   
    }   
  
    class Worker implements Runnable {   
  
        String name;   
        int sleep;   
  
        public Worker(String name, int sleep) {   
            this.name = name;   
            this.sleep = sleep;   
        }   
  
        public void run() {   
            /*upLive(); //计算此线程已经工作.  
            */  
            System.out.println(name+", start to work.");   
            try {   
                Thread.sleep(sleep);    //虚拟工作. 10s 随机时间   
            } catch (InterruptedException e) {   
                System.out.println(name+" interrupted.");   
            }   
            System.out.println(name+", end to work ["+sleep+"] sleep.");   
            /*downLive();   //此线程工作完成  
            */  
        }   
    }   
/*  //记录线程数的同步方法.  
    private synchronized void downLive() {  
        liveThreadNum--;  
    }  
 
    private synchronized void upLive() {  
        liveThreadNum++;  
    }  
 
    private synchronized boolean isLive() {  
        return liveThreadNum > 0;  
    }*/  
  
    public void run() {   
        System.out.println("-------------main run start-------------");   
        int sleepSaid = 10 * 1000;  //每个工作线程虚拟工作最大时间   
        Random rm = new Random();   
        for(int i=0; i<ths.length; i++) {   
            ths[i] = new Thread(new MyTask(rm.nextInt(sleep)+1));   
  
            ths[i].start();   
        }   
  
        for(Thread th : ths) {   
            try {   
                th.join();//join方式   
            } catch (InterruptedException e) {   
                // TODO Auto-generated catch block   
                e.printStackTrace();   
            }   
        }   
        /*//等待所有工作线程完成.  
        while(isLive()) {  
            try {  
                Thread.sleep(1000); //每隔1s查看下是否所有线程完成.  
            } catch (InterruptedException e) {  
                System.out.println("main thread sleep interrupted.");  
            }  
        }*/  
        System.out.println("---------------main run end--------------");   
    }   
  
    public static void main(String[] args) {   
        WaitAllSubThread wast = new WaitAllSubThread(10);   
        wast.run();   
    }   
}  



public class CountDownLatchUse {   
  
    final CountDownLatch downLatch;   
    int n;  //工作线程数   
  
    public CountDownLatchUse(int n) {   
        this.downLatch = new CountDownLatch(n);   
        this.n = n;   
    }   
  
    class Worker implements Runnable {   
  
        String name;   
        int sleep;   
  
        public Worker(String name, int sleep) {   
            this.name = name;   
            this.sleep = sleep;   
        }   
  
        public void run() {   
            System.out.println(name+", start to work.");   
            try {   
                Thread.sleep(sleep);    //虚拟工作. 10s 随机时间   
            } catch (InterruptedException e) {   
                System.out.println(name+" interrupted.");   
            }   
            System.out.println(name+", end to work ["+sleep+"] sleep.");   
            meDone();   //某个工作线程完成   
        }   
    }   
  
    private void meDone() {   
        downLatch.countDown();   
    }   
  
    public void run() {   
        System.out.println("-------------main run start-------------");   
        int sleepSaid = 10 * 1000;  //每个工作线程虚拟工作最大时间   
        Random rm = new Random();   
        for(int i=0; i<n; i++) {   
            new Thread(new Worker("worker-"+i, rm.nextInt(sleepSaid)+1)).start();   
        }   
  
        try {   
            downLatch.await();  //等待所有工作线程完成.   
        } catch (InterruptedException e) {   
            System.out.println("main interrupted.");   
        }   
        System.out.println("---------------main run end--------------");   
    }   
  
    public static void main(String[] args) {   
        CountDownLatchUse mtu = new CountDownLatchUse(10);   
        mtu.run();   
    }   
}
分享到:
评论

相关推荐

    让线程按顺序执行8种方法.doc

    通过使用主线程的join()方法,可以让主线程等待其他线程的执行完成后继续执行。 三、使用线程的wait方法 wait()是Object的方法,作用是让当前线程等待其他线程的唤醒。应用场景:当一个线程需要等待其他线程的结果...

    CountDownLatch与thread.join()的区别

    CountDownLatch与thread.join()的区别

    多线程相关代码(V3)

    多线程相关的(具体包括Lock synchronized Join ThreadLocal Executors CountDownLatch等)一些demo。

    个人总结的深入java多线程开发

    3)线程join()方法 8 4)几种多线程代码写法 10 5)一个超时自动退出程序的类 12 6)同步锁synchronized 13 7)一个程序执行1秒之后自动退出 13 8)线程的状态 14 9)线程阻塞的条件(重要) 14 10) Interrupt()注意事项 16 ...

    Java中的并发工具类.docx

    需求场景:当我们需要解析一个Excel里多个sheet的数据,此时可以考虑使用多...当然我们可以使用join方法,join用于让当前线程等待join线程执行结束。在JDK1.5之后的并发包中提供的CountDownLatch也可以实现join的功能。

    这就是标题—— JUC.pdf

    CountDownLatch (减少计数器) CyclicBarrier(加法计数器) Semaphore(信号量,流量控制) ReentrantReadWriteLock (读写锁) BlockingQueue(阻塞队列) 线程池 池化技术 线程池的优势 线程池的特点 线程池三大...

    Java并发编程原理与实战

    线程的状态以及各状态之间的转换详解.mp4 线程的初始化,中断以及其源码讲解.mp4 多种创建线程的方式案例演示(一)带返回值的方式.mp4 多种创建线程的方式案例演示(二)使用线程池.mp4 Spring对并发的支持:Spring...

    JAVA多线程技术分享-39页PPT(winding)

    分享的多线程技术不是告诉你什么是线程,线程的状态,而是我们在开发中容易踩的坑,受过的伤害。我不会告诉你什么是爱情,但是我会告诉你爱过。 一 基础: 1,Thread.sleep(0)的作用 2,为什么线程会带来性能问题 3...

    Java并发编程应该掌握的并发工具类,快来看看你掌握了哪些?

    1、JUC是什么? JUC是java并发包java.util....这个CountDownLatch可以说是Join()方法的升级版,join用于让当前执行的线程,等待调用join的线程执行结束,然后在接着往下执行。 /** * @Auther: IT贱男 * @Date: 2

    Java并发编程相关技术使用案例

    线程创建、Synchronized和Reentrantlock锁的使用、线程安全问题演示、Condition的应用、CountDownLatch的应用、Cyclicbarrier的应用、Semaphore的应用、线程池的应用、Completablefuture的应用、手写阻塞队列、fork...

    并发编程笔记20190526.docx

    第一章 线程基础、线程之间的共享和协作 3 一、基础概念 3 1. 什么是进程和线程 3 2. CPU核心数和线程数的关系 3 3. 澄清并行和并发 5 4. 多线程程序需要注意事项 6 二、认识Java里的线程 7 1. Java程序天生就是多...

    JAVA并发编程-2-线程并发工具类

    JAVA并发编程-2-线程并发工具类一、Fork/Join1、分而治之与工作密取2、使用标准范式3、Fork/Join的同步用法4、Fork/Join的异步用法二、CountDownLatch三、CyclicBarrier四、Semaphore信号量五、Exchanger ...

    龙果 java并发编程原理实战

    第35节线程之间通信之join应用与实现原理剖析00:10:17分钟 | 第36节ThreadLocal 使用及实现原理00:17:41分钟 | 第37节并发工具类CountDownLatch详解00:22:04分钟 | 第38节并发工具类CyclicBarrier 详解00:11:52...

    Java 并发编程原理与实战视频

    第35节线程之间通信之join应用与实现原理剖析00:10:17分钟 | 第36节ThreadLocal 使用及实现原理00:17:41分钟 | 第37节并发工具类CountDownLatch详解00:22:04分钟 | 第38节并发工具类CyclicBarrier 详解00:11:52...

    龙果java并发编程完整视频

    第35节线程之间通信之join应用与实现原理剖析00:10:17分钟 | 第36节ThreadLocal 使用及实现原理00:17:41分钟 | 第37节并发工具类CountDownLatch详解00:22:04分钟 | 第38节并发工具类CyclicBarrier 详解00:11:52...

    java并发编程

    第35节线程之间通信之join应用与实现原理剖析00:10:17分钟 | 第36节ThreadLocal 使用及实现原理00:17:41分钟 | 第37节并发工具类CountDownLatch详解00:22:04分钟 | 第38节并发工具类CyclicBarrier 详解00:11:52...

    从零基础到深入理解,教你高并发(4.3G)

    05-forkjoin.avi 06-JVM的内存模型.avi 07-volatile.avi 08-多线程的风险.avi 09-CAS.avi 10-线程的状态.avi 11-面试题.avi 12-java.util.concurrent包下的类.avi 13-ReadWriteLock.avi 14-countDownLatch.avi

    java面试题,180多页,绝对良心制作,欢迎点评,涵盖各种知识点,排版优美,阅读舒心

    【多线程】CyclicBarrier 和 CountDownLatch的不同 88 CountDownLatch 88 CyclicBarrier 89 区别: 89 【多线程】简述synchronized 和java.util.concurrent.locks.Lock的异同? 90 【线程】ThreadLocal的作用 90 ...

Global site tag (gtag.js) - Google Analytics