Join方法详解

Join 方法详解

join() 用来等待一个线程的结束,是一种比较”暴力“的线程同步机制,必须等到一个线程结束后另一个线程才开始执行接下来的代码。

同时,join(3000)指定最长等待时间,如果等待时间超过指定的最长等待时间,那么会直接执行下面的方法。

默认无限等待

测试案例1

import java.util.concurrent.TimeUnit;

public class JoinMain {
    public static void main(String[] args) {
        Thread threadA = new Thread(() -> {
            try {
                TimeUnit.SECONDS.sleep(1);
            } catch (InterruptedException e) {
                System.out.println("线程被唤醒");
            }
        }, "threadA");

        Thread threadB = new Thread(() -> {
            try {
                TimeUnit.SECONDS.sleep(2);
            } catch (InterruptedException e) {
                System.out.println("线程被唤醒");
            }
        }, "threadB");


        long begin = System.currentTimeMillis();
        System.out.println("begin: " + begin);

        threadA.start();
        threadB.start();

        // threadA在sleep的时候, threadB也在sleep
        try {
            //-------假设threadA和threadB都已经出于running运行态阶段
            threadA.join();
            //-------此时threadA和threadB都已经睡眠1s
            threadB.join();
            //-------threadB再睡眠1s, 主线程便可以执行后面的逻辑
        } catch (InterruptedException e) {
            throw new RuntimeException(e);
        }

        long end = System.currentTimeMillis();
        System.out.println("end: " + end);

        // 输出结果约等于2s
        System.out.println("run time cost is: " + (end - begin));
    }
}

测试案例2

import java.util.concurrent.TimeUnit;

public class JoinMain {
    public static void main(String[] args) {
        Thread threadA = new Thread(() -> {
            try {
                TimeUnit.SECONDS.sleep(1);
            } catch (InterruptedException e) {
                System.out.println("线程被唤醒");
            }
        }, "threadA");

        Thread threadB = new Thread(() -> {
            try {
                TimeUnit.SECONDS.sleep(2);
            } catch (InterruptedException e) {
                System.out.println("线程被唤醒");
            }
        }, "threadB");


        long begin = System.currentTimeMillis();
        System.out.println("begin: " + begin);

        // threadA在sleep的时候, threadB也在sleep
        try {
            threadA.start();
            //-------假设threadA已经出于running运行态阶段
            threadA.join();
            //-------此时threadA已经睡眠1s, 主线程可以执行启动threadB的代码

            threadB.start();
            //-------假设threadB已经出于running运行态阶段
            threadB.join();
            //-------threadB睡眠2s, 主线程便可以执行后面的逻辑
        } catch (InterruptedException e) {
            throw new RuntimeException(e);
        }

        long end = System.currentTimeMillis();
        System.out.println("end: " + end);

        // 输出结果约等于3s
        System.out.println("run time cost is: " + (end - begin));
    }
}

总结join()方法执行后,如果不满足条件,则调用线程阻塞,不会执行 join() 方法后面的代码。

指定最长等待时间

最长等待时间并不是必须等待指定时间,而是如果在该指定时间内还没结束,则不再等待;如果在该指定时间内结束,也可以执行下面的流程。

测试案例3

import java.util.concurrent.TimeUnit;

public class JoinMain {
    public static void main(String[] args) {
        Thread threadA = new Thread(() -> {
            try {
                TimeUnit.SECONDS.sleep(1);
            } catch (InterruptedException e) {
                System.out.println("线程被唤醒");
            }
        }, "threadA");

        Thread threadB = new Thread(() -> {
            try {
                TimeUnit.SECONDS.sleep(2);
            } catch (InterruptedException e) {
                System.out.println("线程被唤醒");
            }
        }, "threadB");



        long begin = System.currentTimeMillis();
        System.out.println("begin: " + begin);

        // threadA在sleep的时候, threadB也在sleep
        try {
            threadA.start();
            //-------假设threadA已经出于running运行态阶段
            threadA.join();
            //-------此时threadA已经睡眠1s, 主线程可以执行启动threadB的代码

            threadB.start();
            //-------假设threadB已经出于running运行态阶段
            threadB.join(3000);
            //-------threadB睡眠2s, join(3000)至多等待3s, 任一条件满足即可, 因此阻塞时间为: min(max_wait_time, thread_run_time);
        } catch (InterruptedException e) {
            throw new RuntimeException(e);
        }

        long end = System.currentTimeMillis();
        System.out.println("end: " + end);

        // 输出结果约等于3s
        System.out.println("run time cost is: " + (end - begin));
    }
}

   转载规则


《Join方法详解》 熊水斌 采用 知识共享署名 4.0 国际许可协议 进行许可。
 上一篇
Interrupt方法详解 Interrupt方法详解
Interrupt方法详解Interrupt打断阻塞态线程 打断阻塞态的线程会抛出异常,同时清空打断状态。该异常常用来作为唤醒手段 public class InterruptBlockedMain { public stat
2023-03-13
下一篇 
hexo hexo
hexo搭建个人博客下载nodejs使用npm全局安装hexo全局安装的作用是以后没有网络的时候也能建立工程 全局安装淘宝的cnpm, 方便加速 npm install -g cnpm 全局安装hexo cnpm install -
2023-03-13
  目录