Thread.join()与countDownLatch

前言

countDownLatch允许一个或者多个线程等待其他线程完成操作后才能够执行,那么join方法也可以实现这种效果,代码如下,主线程等其他线程执行完以后才能够执行,也就是每次在其他线程在主线程中调用join方法时,main方法所在线程会阻塞进行等待,只有等调用join的线程执行完成,主线程才会执行,join的具体详解可以参考Java多线程join方法实例分析。

Join实现

public class JoinTest {
    static int threadNum = 2;
    public static void main(String[] args) throws InterruptedException {
        for (int i = 0; i < threadNum; i++) {
            Thread thread=new Thread(new _Thread(i + 1));
            thread.start();
            thread.join();
        }
//        只有等线程1和线程2执行完成后主线程才能执行
        System.out.println("线程执行完成的时间为"+System.currentTimeMillis());
    }
}
class _Thread implements Runnable {
    private int id;
    public _Thread(int id) {
        this.id = id;
    }

    @Override
    public void run() {
        System.out.println("线程"+id+"执行的时间为"+ System.currentTimeMillis());
    }
}
运行结果:
线程1执行的时间为1557717528311
线程2执行的时间为1557717528312
线程执行完成的时间为1557717528312

这里对输出结果的顺序做一下解释,由于主线程先开启了线程1,接着阻塞,等线程1结束后才会开启了线程2,所以输出结果顺序总是线程1先输出,接着线程2,再接着主线程。

那么countDownLatch是怎么实现的呢?其实原理上大致是一致的,countDownLatch的构造函数会初始化一个计数器N,线程每调用一次countDown方法,计数器便会减一,可以是N个线程每个都减一,也可以是一个线程调用N个countDown方法,在计数器为0时,调用await方法就不会阻塞当前线程,也就是下面的例子主线程最后执行。注意,如果不在主函数中调用await方法,主线程不会阻塞。

 countDownLatch

public class CountDownLatchTest {

    static int threadNum = 2;
    static CountDownLatch countDownLatch= new CountDownLatch(threadNum);
    public static void main(String[] args) throws InterruptedException {

        for (int i = 0; i < threadNum; i++) {
            new Thread(new MyThread(countDownLatch,i+1)).start();
        }
        countDownLatch.await();
        System.out.println("线程执行完成的时间为"+System.currentTimeMillis());
    }
}

class MyThread implements Runnable {
    private CountDownLatch c;
    private int id;
    MyThread(CountDownLatch c,int id){
        this.c = c;
        this.id = id;
    }
    
    @Override
    public void run() {
        System.out.println("线程"+id+"执行的时间为"+ System.currentTimeMillis());
        c.countDown();
    }
}
运行结果:
线程1执行的时间为1557717738636
线程2执行的时间为1557717738642
线程执行完成的时间为1557717738643

这里线程1和线程2的输出结果顺序不能作保证,两个线程都有可能先执行,顺序有CPU的调度所决定。 

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