天天看点

高并发编程-Thread#join方法的使用及使用场景分析

文章目录

  • ​​含义​​
  • ​​方法及示例​​
  • ​​void join()​​
  • ​​void join(long millis)​​
  • ​​join(long millis, int nanos)​​
  • ​​使用场景分析​​
高并发编程-Thread#join方法的使用及使用场景分析
高并发编程-Thread#join方法的使用及使用场景分析

含义

翻看下源码的注释: Waits for this thread to die

高并发编程-Thread#join方法的使用及使用场景分析

乍理解起来有点晦涩, 简单来说: 等待该线程终止. 需要明确的是主线程等待子线程(假设有个子线程thread)的终止。即在主线程的代码块中,如果碰到了​

​thread.join()​

​方法,此时主线程需要等子线程​

​thread​

​结束了(Waits for this thread to die.),才能继续执行​

​thread.join()​

​之后的代码块。

后面会有示例说明

方法及示例

高并发编程-Thread#join方法的使用及使用场景分析

void join()

重点看注释 ,这里就不多说了。

package com.artisan.test;

import java.util.stream.IntStream;

public class JoinThreadDemo {

    public static void main(String[] args) throws InterruptedException {
        System.out.println(Thread.currentThread().getName() + " 主线程 start");
        System.out.println("------------------------------------------------");

        // 定义一个线程
        Thread t = new Thread(() -> {
            // 打印 1 到 10 的数字
            IntStream.range(0, 10).forEach(i -> System.out.println(Thread.currentThread().getName() + ">>>>>>" + i));
            Optional.of(Thread.currentThread().getName() + " 打印完毕").ifPresent(System.out::println);

        },"artisan-thread");
        // 启动线程
        t.start();
        // 在主线程中 ,开启了一个新的线程t ,调用 t.join方法,确保该线程执行结束后,才会继续执行主线程中剩下的逻辑
        t.join();

        Optional.of("------------------------------------------------").ifPresent(System.out::println);
        System.out.println(Thread.currentThread().getName() + " 主线程 over");
    }
}      

输出:

高并发编程-Thread#join方法的使用及使用场景分析

可以看到 ,调用了 ​

​t.join()​

​ 后, 主线程main线程,一直等到该线程执行结束后,才继续执行main线程自己剩下的业务逻辑。

我们继续来看下在main线程开启多个线程,分别join的情况

package com.artisan.test;

import java.util.Optional;
import java.util.stream.IntStream;

public class JoinThreadDemo {

    public static void main(String[] args) throws InterruptedException {
        System.out.println(Thread.currentThread().getName() + " 主线程 start");
        System.out.println("------------------------------------------------");

        // 定义一个线程
        Thread t = new Thread(() -> {
            // 打印 1 到 10 的数字
            IntStream.range(0, 10).forEach(i -> System.out.println(Thread.currentThread().getName() + ">>>>>>" + i));
            Optional.of(Thread.currentThread().getName() + " 打印完毕").ifPresent(System.out::println);
        },"artisan-thread");

        Thread t2 = new Thread(() -> {
            // 打印 1 到 10 的数字
            IntStream.range(0, 10).forEach(i -> System.out.println(Thread.currentThread().getName() + ">>>>>>" + i));
            Optional.of(Thread.currentThread().getName() + " 打印完毕").ifPresent(System.out::println);
        },"littleART-thread");

        // 启动线程
        t.start();
        t2.start();
        // 在主线程中 ,开启了一个新的线程t ,调用 t.join方法,确保该线程执行结束后,才会继续执行主线程中剩下的逻辑
        t.join();
        t2.join();


        Optional.of("------------------------------------------------").ifPresent(System.out::println);
        System.out.println(Thread.currentThread().getName() + " 主线程 over");
    }
}      

日志输出如下

高并发编程-Thread#join方法的使用及使用场景分析

可以看到 , main线程依然是等待t1和t2执行完以后才继续执行自己的逻辑,但是t1 和 t2 是交替执行的,主要取决于CPU的调度,这是正确的。

void join(long millis)

等待多少毫秒后,如果未完成,继续当前线程的任务。

举个例子来演示下

package com.artisan.test;

import java.util.Optional;
import java.util.stream.IntStream;

public class JoinThreadDemo {

    public static void main(String[] args) throws InterruptedException {
        System.out.println(Thread.currentThread().getName() + " 主线程 start");
        System.out.println("------------------------------------------------");

        // 定义一个线程
        Thread t = new Thread(() -> {
            try {
                // 先休眠10S,再输出 0 到 9
                Thread.sleep(10_000);
                
                Optional.of(Thread.currentThread().getName() + " 休眠结束...继续干活").ifPresent(System.out::println);

                IntStream.range(0, 10).forEach(i -> System.out.println(Thread.currentThread().getName() + ">>>>>>" + i));
                Optional.of(Thread.currentThread().getName() + " 打印完毕").ifPresent(System.out::println);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        },"artisan-thread");

        t.start();
        // t 线程等待 1000毫秒 即 1秒,如果未完成,则不等待,继续主线程中逻辑
        t.join(1000);


        Optional.of("---------------等待1秒结束,继续主线程的业务----------------").ifPresent(System.out::println);
        System.out.println(Thread.currentThread().getName() + " 主线程 over");
    }
}      

输出:

高并发编程-Thread#join方法的使用及使用场景分析

可以看到 线程t在调用 ​

​join(1000)​

​​,等待1秒后,该任务没有完成,主线程继续执行剩下的逻辑, 执行完以后没有退出 是因为​

​t​

​这个线程是user thread ,而不是daemon thread, 所以还是会继续执行的。

join(long millis, int nanos)

这个其实和 ​

​join(long milli)​

​一样 ,只是等待的时间加上纳秒 wait for specified time (milliseconds + nanos). 没啥好演示的了。。。

使用场景分析