Java多线程_join与CountDownLatch

假如有这样一个场景,程序员小余今天的任务是:实现3个需求,修改3个bug,完成这些之后才能下班。可以使用两种方法实现。

1.使用join方法

代码如下:

public class JoinTest {
    public static void main(String[] args) throws InterruptedException{
        Thread thread1 = new Thread(new Runnable(){
            @Override
            public void run() {
                for(int i =1;i<4;i++) {
                    System.out.println( "已实现了第"+i+"需求");
                }
            }
        });
        Thread thread2 = new Thread(new Runnable() {
            @Override
            public void run() {
                for(int i = 1;i<4;i++) {
                    System.out.println("已修改完第"+i+"个Bug");
                }
            }
        });
        thread1.start();
        thread2.start();
        thread1.join();
        thread2.join();
        System.out.println( "任务完成,可以下班了");
    }
}

执行了很多次,结果都符合要求,随机选择一次结果如下:

可以看到,程序员小余是实现完需求并且改完bug才下班的。如果不调用线程1和线程2的join方法话,就不能保证是完成任务后才下班的。查看join方法的实现代码可以看到如下代码:

while (isAlive()) {
    wait(0);
}

其原理就是不停检查join线程是否存活,如果join线程存活则让当前线程永远等待。直到线程中止后,线程的this.notifyAll()方法才会调用,调用notifyAll()方法是在JVM里实现的,所以JDK里看不到。

2.使用CountDownLatch

在JDK1.5之后的并发包中提供了CountDownLatch也可以实现join的功能,它允许一个或多个线程等待其他线程完成操作。
常用API如下:

CountDownLatch(int count) //实例化一个倒计数器,count指定计数个数
countDown() // 计数减一
await() //等待,当计数减到0时,所有线程并行执行

下面使用CountDownLatch来实现之前的代码:

import java.util.concurrent.CountDownLatch;
public class CountDownLatchTest {
    static final CountDownLatch c = new CountDownLatch(6);//构造一个大小的为6的计数器
    public static void main(String[] args) throws InterruptedException {
        Thread thread1 = new Thread(new Runnable(){
            @Override
            public void run() {
                for(int i =1;i<4;i++) {
                    System.out.println( "已实现了第"+i+"需求");
                    c.countDown();//执行一次该线程,计数器减1
                }
            }
        });
        Thread thread2 = new Thread(new Runnable() {
            @Override
            public void run() {
                for(int i = 1;i<4;i++) {
                    System.out.println("已修改完第"+i+"个Bug");
                    c.countDown();//执行一次该线程,计数器减1
                }
            }
        });
        thread1.start();
        thread2.start();
        c.await();//在此处等待,当计数器减到0时,才不会阻塞当前线程,继续往下执行
        System.out.println( "任务完成,可以下班了");
    }
}

CountDownLatch的构造参数接受一个int类型的参数作为计数器,如果想N个线程完成,就传入N。当调用countDown方法时,N就会减1,await方法会阻塞当前线程,直到N变为0.

你可能感兴趣的:(多线程)