前言
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中join方法和CountDownLatch在多线程同步中的应用,详细讲解了它们的工作原理及具体实现方式,通过代码示例展示了如何使用这两种方法来确保线程间的正确执行顺序。
458

被折叠的 条评论
为什么被折叠?



