• 线程常用方法 join


    一、join 方法概述

    等待线程死亡:哪个线程调用 join 方法,那么其它线程会等待该线程执行完成,该方法等价于 join(0)(例如: t1.join() 即其它线程需要等待 t1 线程运行结束)

    主要应用于线程同步,多个 join 是并行执行的

    二、单个 join

    为了探究 join 方法的作用,我们先看下列示例,并猜测结果

    1、代码

    @Slf4j
    public class ThreadDemo {
        private static int i = 1;
    
        public static void main(String[] args) {
            Runnable runnable = () -> {
                log.info("t1 start...");
                try {
                    Thread.sleep(3 * 1000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                i = 10;
                log.info("t1 end...");
            };
    
            Thread t1 = new Thread(runnable, "t1");
            t1.start();
    
            log.info("main start...");
            log.info("i 的值为: {}", i);
            log.info("main end...");
        }
    }
    

    2、运行结果

    从上面的结果可以看出 i 的值为 1,而不是我们在 t1 线程内赋值的 10,如果我们想让 i 最终输出的值为 10,怎么办呢?

    上面的代码理论上可以在 main 线程中也调用 Thread.sleep(time) 方法,只要 time 的值大于 3 * 1000,那么 i 的值就是 10 ,但是不推荐使用此方法,因为在实际的业务场景下,我们不能推断出 t1 线程的真正运行时间,time 的值就不好设定,如果 time 的值设定不合理,那么就有可能得到我们不想得到的结果.

    那么还有其它的解决方式吗?

    这个时候就需要使用 join() 方法了,只需要线程在调用 start() 方法之后调用 join() 方法即可

    3、join 示例代码

    @Slf4j
    public class ThreadDemo {
        private static int i = 1;
    
        public static void main(String[] args) {
            Runnable runnable = () -> {
                log.info("t1 start...");
                try {
                    Thread.sleep(3 * 1000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                i = 10;
                log.info("t1 end...");
            };
    
            Thread t1 = new Thread(runnable, "t1");
            t1.start();
            try {
                t1.join();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            log.info("main start...");
            log.info("i 的值为: {}", i);
            log.info("main end...");
        }
    }
    

    运行结果

    从上面的结果可以看出 i 的值为 10,符合我们的预期(main 线程一直在等待 t1 线程执行完毕之后才运行)

    三、多个线程同时调用 join

    1、代码

    @Slf4j
    public class ThreadDemo {
        private static int i = 1;
        private static int j = 1;
    
        public static void main(String[] args) throws InterruptedException {
            Runnable runnable1 = () -> {
                log.info("t1 start...");
                try {
                    Thread.sleep(3 * 1000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                i = 10;
                log.info("t1 end...");
            };
    
            Runnable runnable2 = () -> {
                log.info("t2 start...");
                try {
                    Thread.sleep(4 * 1000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                j = 20;
                log.info("t2 end...");
            };
    
            Thread t1 = new Thread(runnable1, "t1");
            Thread t2 = new Thread(runnable2, "t2");
    
            t1.start();
            t2.start();
    
            long start = System.currentTimeMillis();
            t1.join();
            t2.join();
            long end = System.currentTimeMillis();
            log.info("i: {} j: {} cost: {}", i, j, end - start);
        }
    }
    

    2、运行结果

    等待 t1 运行完毕需要 3s,等待 t2 运行完毕需要 4s, t1,t2 同时调用 join() 方法,最终消耗的时间是 4014 ms,可以看出 t1、t2 是并行执行的

     

    3、如果将 t1.join() 和 t2.join() 调换位置,会得到什么结果呢?

    可以看出,最终等待的时间还是 4014 ms,从而进一步印证了多个线程同时调用 join() 方法是并行执行的

    四、join 的其它重载方法

    等待该线程死亡的时间最长时间(单位为毫秒),超时为 0 意味着永远等待,如果在等待的时间内线程提前结束,那么等待时间就是线程结束的时间(例如 join(3*1000),而线程执行完成需要 2000 ms,那么等待的时间也是 2000 ms)

     

  • 相关阅读:
    zabbix笔记之计算型监控项详解
    zabbix笔记之磁盘IO介绍
    zabbix笔记之Graphtree配置
    zabbix笔记之告警时远程执行命令
    zabbix笔记之异常优化
    zabbix笔记之IPMI配置
    基本的sql 语句
    socket 套接字
    调用父类的三种方法
    实例属性和类属性
  • 原文地址:https://www.cnblogs.com/xiaomaomao/p/15894441.html
Copyright © 2020-2023  润新知