8. Java并发编程的魅力之 Join的用法

0x01 构造需求

现在假如我们有这样一个需求:

我们需要解析一个Excel 里多个Sheet 的数据,为了加快解析的速度,此时可以考虑使用多线程。

实现思路如下:

  • 每个线程解析一个sheet 里面的数据。
  • 等到所有的Sheet 都解析完成后,程序需要提示解析完成。

0x02 解决思路

2.1 菜鸟的错误写法

如果是一个新手菜鸟不懂Java 并发的话,可能会这么写:

/**
 * @author qing-feng.zhao
 * @功能
 * @时间 2020/1/20 14:22
 */
public class JoinSampleTest{
    public static void main(String[] args){
        Thread thread1=new Thread(new Runnable(){
            @Override
            public void run(){
                System.out.println("start to parse excel sheet one");
            }
        });
        Thread thread2=new Thread(new Runnable(){
            @Override
            public void run(){
                System.out.println("start to parse excel sheet two");
            }
        });
        thread1.start();
        thread2.start();
        System.out.println("all parse finished");
    }
}

这样写的结果你们猜会怎么样?

结果可能会输出这样:

all parse finished
start to parse excel sheet one
start to parse excel sheet two

当然由于线程执行先后顺序的不可确定性,还可能会输出这样的结果:

all parse finished
start to parse excel sheet two
start to parse excel sheet one

但是不管怎么样,这两种结果绝对都不是我们想要的。

我们其实希望的是线程一和线程二执行完成后,再输出 all parse finished 好不?

这还没干完活呢,就告诉领导干完活了,这样可不好吧?

2.2 懂并发编程的正确写法

那么到底应该怎么做才能达到我们想要的效果呢?

如果请教大神,大神可能会告诉你最简单的一种写法是使用join()方法。

那么接下来就让我们试试join()方法的神奇魅力。

/**
 * @author qing-feng.zhao
 * @功能
 * @时间 2020/1/20 14:22
 */
public class JoinSampleTest{
    public static void main(String[] args){
        Thread thread1=new Thread(new Runnable(){
            @Override
            public void run(){
                System.out.println("start to parse excel sheet one");
            }
        });
        Thread thread2=new Thread(new Runnable(){
            @Override
            public void run(){
                System.out.println("start to parse excel sheet two");
            }
        });
        thread1.start();
        thread2.start();

        try {
            thread1.join();
        } catch (InterruptedException e) {
            System.err.println("thread1 join error"+e);
        }

        try {
            thread2.join();
        } catch (InterruptedException e) {
            System.err.println("thread2 join error"+e);
        }
        System.out.println("all parse finished");
    }
}

执行后会输出如下结果:

start to parse excel sheet one
start to parse excel sheet two
all arse finished

诶,果然可以了哈。

0x03 join方法分析

join() 这么神奇,那么到底是怎么回事呢?

  • 上面代码中我们关心的有三个线程,主线程,线程一,线程二
  • 我们希望线程一和线程二执行完成后,再输出一句话,所有线程都解析完了。
  • join 的作用就是让当前执行线程等待join线程执行结束。
  • 也就是说主线程中会等待thread1.join();和thread2.join() 方法执行完成后,才会执行最后一行的输出打印语句代码。
  • 其实现原理是不停检查join线程是否存活,如果join线程存活则让当前线程永远等待。
  • 其中,wait(0)表示永远等待下去,代码片段如下
while(isAlive()){
    wait(0);
}
  • 直到join线程中止后,线程的this.notifyAll()方法会被调用
  • 调用notifyAll()方法是在JVM里实现的,所以在JDK里看不到,大家可以查看JVM源码。

本篇完~

更多精彩内容请关注博客专栏 Java并发编程的魅力 ,持续更新中。。。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

极客星云

谢谢认可,希望对你的学习有帮助

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值