多线程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!");
       
       
    }
}

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/a5d706806d22bf23aa71970c5ed99fe0.html