线程合并 (join)

从Java线程到kotlin协程 专栏收录该内容
15 篇文章 2 订阅

上一篇:
线程休眠 (sleep)

线程合并(join)

将指定的线程加入到当前线程,当前线程会处于 WAITING 状态,直到引用的线程死亡(出现异常或者执行完毕),然后当前线程再继续执行。
先来看看join方法源码

在这里插入图片描述
可以看到,join调用了另外一个重载的方法,我们再看看重载的那个方法。
在这里插入图片描述
可以看到,join方法最终调用的是一个同步方法,接收一个毫秒值。

我们来简单用一用:

有以下代码

    public static void main(String[] args) {

        Thread thread = new Thread(() -> {
            for (int i = 0; i < 30; i++) {
                try {
                    TimeUnit.MILLISECONDS.sleep(10);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                System.out.println(Thread.currentThread().getName() + i);
            }

        }, "work");
        thread.start();
        for (int i = 0; i < 30; i++) {
            try {
                TimeUnit.MILLISECONDS.sleep(10);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println(Thread.currentThread().getName() + i);
        }

    }

上面代码运行结果是work线程和main线程交替打印的,这个没啥好说的。
在这里插入图片描述

如果我们想先让work线程执行完毕,然后再执行主线程。可以这样写:

    public static void main(String[] args) {

        Thread thread = new Thread(() -> {
            for (int i = 0; i < 5; i++) {
                System.out.println(Thread.currentThread().getName() + i);
            }

        }, "work");
        thread.start();

        /*合并线程*/
        try {
            thread.join();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

        /*work线程的状态*/
        System.out.println(thread.getName() + "的状态:" + thread.getState());

        for (int i = 0; i < 5; i++) {
            System.out.println(Thread.currentThread().getName() + i);
        }

    }

运行结果如下:
在这里插入图片描述

可以看到,work线程执行完毕,且状态是 TERMINATED 后,主线程才继续执行的。

这个时候你可能就有疑问了,这不就是单线程执行吗,完全提体现不出join的意义啊。

如果你有这个问题,那我只能说
在这里插入图片描述

下面我们来看一个Join的使用场景。

之前我写过一篇博客

高德逆地理编码接口返回数据格式不统一以及百度逆地理编码接口返回数据解析失败的踩坑记录

大体是我需要同时调高德和百度的逆地理编码接口,把两个接口返回的数据合并一下使用,当时用的是RxJava的zip操作符实现的,现在的话当然是用kotlin的协程更简洁了。

其实,用Join实现也是ok的,为了方便,这里就用 kotlin 写了

fun main() {
    /*模拟高德接口返回的结果*/
    var gaodeResult = ""
    /*模拟高德接口返回的结果*/
    var baiduResult = ""

    /*高德线程*/
    val gaoDeThread = Thread({
        println("${Thread.currentThread().name}开始调用...")
        TimeUnit.SECONDS.sleep(2)
        println("${Thread.currentThread().name}调用完毕...")

        gaodeResult = "gaode"

    }, "GaoDe")
    /*高德线程*/
    val baiduThread = Thread({
        println("${Thread.currentThread().name}开始调用...")
        TimeUnit.SECONDS.sleep(2)
        println("${Thread.currentThread().name}调用完毕...")
        baiduResult = "baidu"
    }, "BaiDu")

    /*启动两个线程*/
    gaoDeThread.start()
    baiduThread.start()


    /*合并两个线程*/
    gaoDeThread.join()
    baiduThread.join()

    /*主线程拿到的结果*/
    println("${Thread.currentThread().name}===>${gaodeResult}---${baiduResult}")
}

来看下运行结果:

在这里插入图片描述

可以看到,用Join其实也能实现之前的需求。
这里跟单线程执行的区别就能看出来了,在单线程中,是没办法做到并发请求的。

join(long millis)

将指定的线程加入到当前线程,当前线程会处于 WAITING 状态,指定线程占用cpu资源执行任务,持续时间为millis,持续时间完毕后,指定线程将不再占用cpu资源,而是跟当前线程去争夺cpu资源。

示例代码:

fun main() {

    val thread = Thread {

        for (i in 1..10) {
            TimeUnit.MILLISECONDS.sleep(100)
            println("${Thread.currentThread().name}===》${i}")
        }
    }
    thread.start()
    /*join 500毫秒*/
    thread.join(500)
    for (i in 1..10) {
        TimeUnit.MILLISECONDS.sleep(100)
        println("${Thread.currentThread().name}===》${i}")
    }
}

运行结果:
在这里插入图片描述
可以看到,前5次打印是Thread-0 独自打印,join时间过后,开始和main线程交替打印。

好了,join大概就是这些

下一篇:

线程同步之synchronized关键字


如果你觉得本文对你有帮助,麻烦动动手指顶一下,可以帮助到更多的开发者,如果文中有什么错误的地方,还望指正,转载请注明转自喻志强的博客 ,谢谢!

  • 0
    点赞
  • 1
    评论
  • 0
    收藏
  • 一键三连
    一键三连
  • 扫一扫,分享海报

相关推荐
©️2020 CSDN 皮肤主题: 书香水墨 设计师:CSDN官方博客 返回首页
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值