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. Codeforces Round #672 (Div. 2) D. Rescue Nibel!(排序)

    题目链接:https://codeforces.com/contest/1420/problem/D 前言 之前写过这场比赛的题解,不过感觉这一题还可以再单独拿出来好好捋一下思路. 题意 给出 $n$ ...

  2. Codeforces Round #665 (Div. 2) D - Maximum Distributed Tree dfs贡献记录

    题意: t组输入,每组数据中n个节点构成一棵树,然后给你n-1条边.给你一个m,然后给你m个k的素数因子,你需要给这n-1条边都赋一个权值,这n-1条边的权值之积应该等于k.如果k的素数因子数量小于n ...

  3. KMP——POJ-3461 Oulipo && POJ-2752 Seek the Name, Seek the Fame && POJ-2406 Power Strings && POJ—1961 Period

    首先先讲一下KMP算法作用: KMP就是来求在给出的一串字符(我们把它放在str字符数组里面)中求另外一个比str数组短的字符数组(我们叫它为ptr)在str中的出现位置或者是次数 这个出现的次数是可 ...

  4. Dire Wolf——HDU5115

    Dire wolves, also known as Dark wolves, are extraordinarily large and powerful wolves. Many, if not ...

  5. 牛客小白月赛17 A 小sun的假期

    传送门 题意: 第一行两个数n,m,代表总共有n天,m个安排.接下来有m行,每行是一个安排l,r,代表从第l天到第r天,小sun有安排了.安排可能会重复. 小 sun 非常喜欢放假,尤其是那种连在一起 ...

  6. C# 网络加密与解密

    数据在网络传输过程中的保密性是网络安全中重点要考虑的问题之一.由于通过网络传递数据是在不安全的信道上进行传输的,因此通信双方要想确保任何可能正在侦听的人无法理解通信的内容,而且希望确保接收方接收的信息 ...

  7. 部署开源IP管理工具phpIPAM

    一.安装环境程序: yum install httpd mariadb-server php php-cli php-gd php-common php-ldap php-pdo php-pear p ...

  8. 9.[完]其他常用的rabbitmq的参数和设置

    作者 微信:tangy8080 电子邮箱:914661180@qq.com 更新时间:2019-08-12 20:42:25 星期一 欢迎您订阅和分享我的订阅号,订阅号内会不定期分享一些我自己学习过程 ...

  9. history-back

    ;!function(pkg, undefined){ //此声明函数在xback.js文件里有,在app.js里必须再声明一次,不然监听返回事件失败 var STATE = 'x-back'; va ...

  10. Leetcode(206)-反转链表

    反转一个单链表. 示例: 输入: 1->2->3->4->5->NULL 输出: 5->4->3->2->1->NULL 思路:反转链表很简 ...