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方法也是一种选择;

  • 相关阅读:
    There is an overlap in the region chain修复
    There is an overlap in the region chain
    region xx not deployed on any region server
    python 中的re模块,正则表达式
    TCP粘包问题解析与解决
    yield from
    Git push提交时报错Permission denied(publickey)...Please make sure you have the correct access rights and the repository exists.
    mysql 中Varchar 与char的区别
    Mysql 字符集及排序规则
    请实现一个装饰器,限制该函数被调用的频率,如10秒一次
  • 原文地址:https://www.cnblogs.com/cfyrwang/p/6484139.html
Copyright © 2011-2022 走看看