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】边叫边练。

join为啥会阻塞主线程?的更多相关文章

  1. 关于ViewPager设置属性页setCurrentItem会阻塞主线程ANR总结

    关于android开发设置View Pager的直接跳转页set CurrentItem会阻塞主线程ANR. 根据网上解决的说法,分析源码: if (mFirstLayout) { // We don ...

  2. Kafka producer异步发送在某些情况会阻塞主线程,使用时候慎重

    最近发现一个Kafka producer异步发送在某些情况会阻塞主线程,后来在排查解决问题过程中发现这可以算是Kafka的一个说明不恰当的地方. 问题说明 在很多场景下我们会使用异步方式来发送Kafk ...

  3. C# 多线程join的用法,等待多个子线程结束后再执行主线程

    等待多个子线程结束后再执行主线程 class MultiThread{ #region join test public void MultiThreadTest() { Thread[] ths = ...

  4. python 之 并发编程(进程池与线程池、同步异步阻塞非阻塞、线程queue)

    9.11 进程池与线程池 池子使用来限制并发的任务数目,限制我们的计算机在一个自己可承受的范围内去并发地执行任务 池子内什么时候装进程:并发的任务属于计算密集型 池子内什么时候装线程:并发的任务属于I ...

  5. C#新开一个线程取到数据,如何更新到主线程UI上面

       一:问题 之前有被面试官问过,在WinForm中,要去网络上获取数据,由于网络环境等原因,不能很快的完成,因此会发生进程阻塞,造成主进程假死的现象,需要怎么解决?    二:思路 因此,往往是新 ...

  6. AnimateWindow 阻塞当前线程问题

    今天查了蛮多的,虽然不是系统的学习,收获也不小.下面说一下我的解决方法: 问题一:采用 AnimateWindow API实现消息窗体FormMsg的动画出现,但由于该方法会阻塞当前线程,造成其他窗体 ...

  7. [置顶] 使用严苛模式打破Android4.0以上平台应用中UI主线程的“独断专行”

    传送门 ☞ 轮子的专栏 ☞ 转载请注明 ☞ http://blog.csdn.net/leverage_1229 已经有好一段时间没有关注Android应用方面的事情了:)最近单位来了一个Androi ...

  8. Qt中运行后台线程不阻塞UI线程的方案

    有一个想法,一个客户端,有GUI界面的同时也要向网络服务器发送本地采集的数据,通过网络发送数据的接口是同步阻塞的,需要等待服务器响应数据. 如果不采用后台线程的方案,用主UI线程关联一个定时器QTim ...

  9. 千万别在UI线程上调用Control.Invoke和Control.BeginInvoke,因为这些是依然阻塞UI线程的,造成界面的假死

    原文地址:https://www.cnblogs.com/wangchuang/archive/2013/02/20/2918858.html .c# Invoke和BeginInvoke 区别 Co ...

随机推荐

  1. MySQL 企业案例:误删核心业务表

    问题描述: 1.正在运行的网站系统,MySQL 数据库,数据量 25G,日业务增量 10 - 15M 2.备份策略:每天 23:00,计划任务调用 mysqldump 执行全备脚本 3.故障时间点:上 ...

  2. 关于TCP和UDP的通俗理解

    TCP和UDP是网络基础,很多公司面试也都会问到,今天我在这里,根据大神们的讲解,自己总结借鉴一下. 首先,先提一个问题:英雄联盟是TCP还是UDP? 这个问题对于游戏玩家,可能大多数人都没有想过.一 ...

  3. 翻译:《实用的Python编程》01_02_Hello_world

    目录 | 上一节 (1.1 Python) | 下一节 (1.3 数字) 1.2 第一个程序 本节讨论有关如何创建一个程序.运行解释器和调试的基础知识. 运行 Python Python 程序始终在解 ...

  4. LeetCode & Binary Search 解题模版

    LeetCode & Binary Search 解题模版 In computer science, binary search, also known as half-interval se ...

  5. javascript change array length methods

    javascript change array length methods Array 改变数组长度的方法 push, pop shift, unshift, splice, fill, 不改变数组 ...

  6. nvm install node error

    nvm install node error ➜ mini-program-all git:(master) nvm install 10.15.3 Downloading and installin ...

  7. modal over table bug

    modal over table bug table can not clickable bad <el-row> <el-col :span="24"> ...

  8. vue mixin执行覆盖

    https://cn.vuejs.org/v2/guide/mixins.html 完整代码 vue-option-overwrite-strategies vue 自带的mixin如果钩子函数重复会 ...

  9. vue动态添加当前事件下的class

    html部分<div class="star"> <span v-for="(item,index) in 5" @click="c ...

  10. Error Code: 1452 Cannot add or update a child row: a foreign key constraint fails

    错误: Error Code: 1452 Cannot add or update a child row: a foreign key constraint fails 错误产生情景:我向一张带外键 ...