zoukankan      html  css  js  c++  java
  • 多线程CountDownLatch和Join

    如果现在有五个线程A、B、C、D、E,请问如何用E线程用于统计A、B、C、D四个线程的结果?

    题意需要用E线程统计A、B、C、D四个线程,也就是说E线程必须要等到前面四个线程运行结束之后才能执行。那么如何使用E线程来统计前面四个线程的结果呢?

    下面介绍两种实现方法:

    一、CountDownLatch

    CountDownLatch是一种java.util.concurrent包下一个同步工具类,它允许一个或多个线程等待直到在其他线程中一组操作执行完成。

    我们可以将CountDownLatch看作一个计数器,可以给定其一个数来对其进行初始化。当它计数的值变为0时,才可以执行后续的步骤。

    public CountDownLatch(int count)
    

    CountDownLatch有两个方法是我们常用的:await();和countDown();

    await()函数用于阻塞当前线程直到CountDownLatch的计数值变为0;

    countDown()方法用于将当前CountDownLatch的计数值减1;

    简单的介绍了CountDownLatch的作用和用法之后,我们看下如下的代码:

    import java.util.concurrent.CountDownLatch;
    public class  Test1{
        public static void main(String[] args) throws InterruptedException {
            int number = 3;
            CountDownLatch latch =  new CountDownLatch(number);
            
            for(int i=0;i<3;i++){
                ThreadDemo demo = new ThreadDemo(latch);
                demo.start();
                System.out.println(i);
            }
            latch.await();
            System.out.println("Check it Out");
        }
    }
    
    class ThreadDemo extends Thread{
        
        private CountDownLatch latch;
        
        public ThreadDemo(CountDownLatch latch){
            this.latch = latch;
        }
        
        public void run(){
            try {
                Thread.sleep(5000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            latch.countDown();
        }
    }

    我们首先创建了一个CountDownLatch对象给定一个number将其初始化,需要注意的是当前CountDownLatch对象的值减为0之后,该对象便失去了作用。

    同时我们提供了继承自Thread的ThreadDemo类,它包含了一个CountDownLatch对象。当我们创建ThreadDemo对象时,会将CountDowmLatch对象注入其中。

    在TreadDemo类的run()方法中,我们执行了两步动作:延迟5秒后将CountDownLatch的计数值减1。

    在main函数中,我们利用for循环创建了三个ThreadDemo对象并执行他们的run()方法。添加和不添加latch.await()语句将会得到两种执行结果。

    1、添加latch.await()语句

      执行结果:

      0

      1

      2

      Check it Out

      我们会发现0 1 2几乎是同时打印出来的,但是“Check it Out”大概等待了5秒左右的时间后才打印,这说明了其实“Check it Out”是等待前面三个线程执行完countDown()方法之后将latch的值减为0之后才执行的。

    2、无latch.await()语句

      执行结果:

      0

      1

      2

      Check it Out

      观察运行结果我们会发现,0 1 2和“Check it Out”几乎是同时出现的,也就是说“Check it Out”并没有等待前面三个线程执行完成之后才执行。

      CountDowLlatch的用途即是让一组线程先执行,知道countdownlatch对象的计数值到0后,让后续的线程继续执行。

    二、join方法实现

       事实上,join方法也可以实现同样的效果!代码如下:

    import java.util.concurrent.CountDownLatch;
    public class  Test{
        public static void main(String[] args) throws InterruptedException {
            int number = 3;
            CountDownLatch latch =  new CountDownLatch(number);
            ThreadDemo thread1 = new ThreadDemo(1);
            ThreadDemo thread2 = new ThreadDemo(2);
            thread1.start();
            thread1.join();
            System.out.println("----");
            thread2.start(); 
            thread2.join();
            System.out.println("main is end!");
            
            
        }
    }
    
    class ThreadDemo extends Thread{
        private int number;
        public ThreadDemo(int number){
            this.number = number;
        }
        public void run(){
            System.out.println("Thread"+number+" is running");
            try {
                Thread.sleep(5000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println("Thread"+number+"is end");
        }
    }

    运行结果如下:

    Thread1 is running

    Thread1is end

    ----

    Thread2 is running

    Thread2is end

    main is end!

    可以看到thread1阻塞了thread2,只有当thread1和thread2均执行结束后,main方法才能继续执行。如果想要thread1和thread2同时执行的话,只需要做如下简单的变动。

    thread1.start();
    thread1.join();
    thread2.start(); 
    thread2.join();
      
    System.out.println("main is end!");

    运行结果如下:

    Thread1 is running

    Thread2 is running

    Thread1is end

    Thread2is end

    main is end!

    因此,如果我们需要某些线程等待指定任务执行完毕之后执行,选择join方法也是一种选择;

  • 相关阅读:
    zTree 优秀的jquery树插件
    The underlying provider failed on open 问题解决
    HTML 5 <input> list 属性
    C#拖曳控件加载,bll报错问题
    把VS2010的智能代码提示和注解从英文变成中文
    progressBar的使用
    C++内存读写例子
    bash 管理小脚本
    KVM虚拟机配置笔记
    Ettercap 实施中间人攻击
  • 原文地址:https://www.cnblogs.com/cfyrwang/p/6484139.html
Copyright © 2011-2022 走看看