join为啥会阻塞主线程?
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为啥会阻塞主线程?的更多相关文章
- 关于ViewPager设置属性页setCurrentItem会阻塞主线程ANR总结
关于android开发设置View Pager的直接跳转页set CurrentItem会阻塞主线程ANR. 根据网上解决的说法,分析源码: if (mFirstLayout) { // We don ...
- Kafka producer异步发送在某些情况会阻塞主线程,使用时候慎重
最近发现一个Kafka producer异步发送在某些情况会阻塞主线程,后来在排查解决问题过程中发现这可以算是Kafka的一个说明不恰当的地方. 问题说明 在很多场景下我们会使用异步方式来发送Kafk ...
- C# 多线程join的用法,等待多个子线程结束后再执行主线程
等待多个子线程结束后再执行主线程 class MultiThread{ #region join test public void MultiThreadTest() { Thread[] ths = ...
- python 之 并发编程(进程池与线程池、同步异步阻塞非阻塞、线程queue)
9.11 进程池与线程池 池子使用来限制并发的任务数目,限制我们的计算机在一个自己可承受的范围内去并发地执行任务 池子内什么时候装进程:并发的任务属于计算密集型 池子内什么时候装线程:并发的任务属于I ...
- C#新开一个线程取到数据,如何更新到主线程UI上面
一:问题 之前有被面试官问过,在WinForm中,要去网络上获取数据,由于网络环境等原因,不能很快的完成,因此会发生进程阻塞,造成主进程假死的现象,需要怎么解决? 二:思路 因此,往往是新 ...
- AnimateWindow 阻塞当前线程问题
今天查了蛮多的,虽然不是系统的学习,收获也不小.下面说一下我的解决方法: 问题一:采用 AnimateWindow API实现消息窗体FormMsg的动画出现,但由于该方法会阻塞当前线程,造成其他窗体 ...
- [置顶] 使用严苛模式打破Android4.0以上平台应用中UI主线程的“独断专行”
传送门 ☞ 轮子的专栏 ☞ 转载请注明 ☞ http://blog.csdn.net/leverage_1229 已经有好一段时间没有关注Android应用方面的事情了:)最近单位来了一个Androi ...
- Qt中运行后台线程不阻塞UI线程的方案
有一个想法,一个客户端,有GUI界面的同时也要向网络服务器发送本地采集的数据,通过网络发送数据的接口是同步阻塞的,需要等待服务器响应数据. 如果不采用后台线程的方案,用主UI线程关联一个定时器QTim ...
- 千万别在UI线程上调用Control.Invoke和Control.BeginInvoke,因为这些是依然阻塞UI线程的,造成界面的假死
原文地址:https://www.cnblogs.com/wangchuang/archive/2013/02/20/2918858.html .c# Invoke和BeginInvoke 区别 Co ...
随机推荐
- mysql创建和使用数据库
mysql连接和断开 mysql -h host -u user -p******** /*建议不要在命令行中输入密码,因为这样做会使其暴露给在您的计算机上登录的其他用户窥探*/ mysql -u u ...
- Windows10与虚拟机中CentOS-7.2进行ftp通信
首先Linux的IP地址可以通过以下命令获取: ifconfig Windows10上面IP地址通过下面命令获取 ipconfig 你首先要保证你的主机和Linux虚拟机是可以ping通的(ping都 ...
- 【uva 11082】Matrix Decompressing(图论--网络流最大流 Dinic+拆点二分图匹配)
题意:有一个N行M列的正整数矩阵,输入N个前1~N行所有元素之和,以及M个前1~M列所有元素之和.要求找一个满足这些条件,并且矩阵中的元素都是1~20之间的正整数的矩阵.输入保证有解,而且1≤N,M≤ ...
- Codeforces Round #582 (Div. 3) E. Two Small Strings (构造,思维,全排列)
题意:给你两个长度为\(2\)的字符串\(s\)和\(t\),你需要构造一个长度为\(3n\)的字符串,满足:含有\(n\)个\(a\),\(n\)个\(b\),\(n\)个\(c\),并且\(s\) ...
- Codeforces Round #656 (Div. 3) B. Restore the Permutation by Merger (模拟)
题意:有两个完全相同的排列,将其中一个的元素按相对顺序插入另外一个排列中,给你操作完的排列,求原排列. 题解:感觉看看样例就能直接写了啊,直接遍历,用桶存数字个数,如果桶为空,直接输出即可. 代码: ...
- Qt内部的d指针和q指针手把手教你实现
Qt内部的d指针和q指针 在讲Qt的D指针之前让我们来简单的解释一下D指针出现的目的,目的是什么呢?保证模块间的二进制兼容. 什么是二进制兼容呢,简单说就是如果自己的程序使用了第三方模块,二进制兼容可 ...
- leetcode 36 有效的数独 哈希表 unordered_set unordersd_map 保存状态 leetcode 37 解数独
leetcode 36 感觉就是遍历. 保存好状态,就是各行各列还有各分区divide的情况 用数组做. 空间小时间大 class Solution { public: bool isValidSud ...
- C# 类 (11) - Const
Const variable 变量 ,值可变的constant 常量,不可变,C# 里关键字是const当我们定义一个常量的时候,需要立马赋值,以后不能再改这个量了我们可以把常量定义在 method ...
- Gym 101480F Frightful Formula(待定系数)题解
#include<cmath> #include<set> #include<map> #include<queue> #include<cstd ...
- Spring框架整合Mybatis项目
第一步:导入相关依赖jar包 <dependency> <groupId>org.mybatis</groupId> <artifactId>mybat ...