join使用


上篇我们介绍了CountDownLatch,顺便说到了Thread中的join方法!

import java.util.concurrent.TimeUnit;/** * @author :jiaolian * @date :Created in 2021-02-28 21:43 * @description:join测试 * @modified By: * 公众号:叫练 */public class JoinTest {    public static void main(String[] args) throws InterruptedException {        Thread threadA = new Thread(()->{            try {                TimeUnit.SECONDS.sleep(2);            } catch (InterruptedException e) {                e.printStackTrace();            }            System.out.println(Thread.currentThread().getName()+":想先执行");        },"线程A");        //开启一个线程A        threadA.start();        //主线程会持有子线程的锁,子线程还没开始主线程就阻塞了,等待子线程结束后通知;        threadA.join();        System.out.println(Thread.currentThread().getName()+ "线程执行");    }}

如上代码所示:在JoinTest开启一个线程A,threadA调用join()方法,主线程会等待threadA执行完毕!也就是两秒后,主线程执行最后一句话,运行结果如下图所示!

我们深入源码,join方法底层其实就是一个wait方法,但现在问题是:明明调用者是线程A,可阻塞的是mian线程,不应该阻塞的是threadA吗?


证明问题:明明调用者是线程A,可阻塞的是mian线程


我们参照Thread中join源码,将上面的代码改造如下:

import java.util.concurrent.TimeUnit;/** * @author :jiaolian * @date :Created in 2021-02-28 21:43 * @description:join测试 * @modified By: * 公众号:叫练 */public class JoinCodeTest {    public static void main(String[] args) throws InterruptedException {        MyThread threadA = new MyThread("线程A");        //开启一个线程A        threadA.start();        //主线程会持有子线程的锁,子线程还没开始主线程就阻塞了,等待子线程结束后通知;        threadA.join2(0);        System.out.println(Thread.currentThread().getName()+ "线程执行");    }    private static class MyThread extends Thread {        public MyThread(String name) {            super(name);        }        @Override        public void run() {            try {                TimeUnit.SECONDS.sleep(2);            } catch (InterruptedException e) {                e.printStackTrace();            }            System.out.println(Thread.currentThread().getName()+":想先执行");        }        //复制Thread源码中的join方法测试阻塞的是线程A还是main线程?        public final synchronized void join2(long millis)                throws InterruptedException {            long base = System.currentTimeMillis();            long now = 0;            if (millis < 0) {                throw new IllegalArgumentException("timeout value is negative");            }            if (millis == 0) {                while (isAlive()) {                    //虽然调用者是线程A,但真正执行阻塞的是main线程!                    System.out.println(Thread.currentThread().getName()+"会阻塞");                    wait(0);                }            } else {                while (isAlive()) {                    long delay = millis - now;                    if (delay <= 0) {                        break;                    }                    wait(delay);                    now = System.currentTimeMillis() - base;                }            }        }    }}

如上代码所示:MyThread继承Thread,并复制了join源码,将join修改成join2,并在join2方法中增加了一个输出语句,System.out.println(Thread.currentThread().getName()+"会阻塞")用来测试阻塞的是线程A还是main线程,所以在JoinCodeTest的main方法中ThreadA是调用join2方法,

结果发现进入join2方法的线程是main线程。运行结果如下图所示!

这里可以把join理解成一个普通方法!真正阻塞的不是调用者线程,而是当前正在执行的线程。


总结


今天我们介绍了join方法,特别是将源码中代码copy出来证明测试,相信整理出来希望能对你有帮助,写的比不全,同时还有许多需要修正的地方,希望亲们加以指正和点评,喜欢的请点赞加关注哦。点关注,不迷路,我是叫练公众号,微信号【jiaolian123abc】边叫边练。




©著作权归作者所有:来自51CTO博客作者叫练的原创作品,如需转载,请注明出处,否则将追究法律责任

好知识,才能预见未来

赞赏

0人进行了赞赏支持

更多相关文章

  1. 【java】网络编程之BIO
  2. 基于单节点redis实现分布式锁
  3. 基于数据库实现分布式锁
  4. 从GC的SuppressFinalize方法带你深刻认识Finalize底层运行机制
  5. 不要把异常当做业务逻辑,这性能可能你无法承受
  6. 同步异步多线程这三者关系,你能给面试官一个满意的回答吗?
  7. 多线程基础知识
  8. 【金三银四】Java并发编程面试题(2021最新版)
  9. 怎么给女朋友讲明白线程池?

随机推荐

  1. php中的文件包含
  2. PHP格式化日期,显示“刚刚,几分钟前,几小时
  3. 在多维数组中查找最小值并返回键
  4. PHP Word上的短网址
  5. 一个关于用php输出文件的问题(急)
  6. 您是否认为PHP中的错误形式是在类方法中
  7. 040-PHP使用闭包函数来进行父实例的变量
  8. 如何通过PHP将HTML页面作为字符串获取?
  9. Php DateTime :: setDate()不在第一个DateP
  10. 使用ajax在服务器端恢复json时出错