一起学并发编程
来源:互联网 发布:linux vi编辑器 查找 编辑:程序博客网 时间:2024/05/01 15:38
由于前段时间比较忙,线程这快学习停滞了,只能利用周日的时间来写写博客了,
多线程Join方法
的作用就是把指定的线程加入到当前线程,让主线程
等待子线程
结束之后才能继续运行,从而完成同步操作
介绍
join()
的作用:让主线程
等待子线程
结束之后才能继续运行,首先先来看下以采集
为案例的代码,统计采集所消耗的时长
需求:当所有线程任务执行完毕,统计最终消耗时长
public class ThreadJoin { public static void main(String[] args) throws InterruptedException { long startTime = System.currentTimeMillis(); Thread t1 = new Thread(new CaptureRunnable("M1", 5_000L)); Thread t2 = new Thread(new CaptureRunnable("M2", 3_000L)); Thread t3 = new Thread(new CaptureRunnable("M3", 2_000L)); t1.start(); t2.start(); t3.start(); System.out.println("采集完成,消耗 " + (System.currentTimeMillis() - startTime)); }}class CaptureRunnable implements Runnable { private String machineName;//采集任务名 private Long spendTime;//采集工作消耗时长 public CaptureRunnable(String machineName, Long spendTime) { this.machineName = machineName; this.spendTime = spendTime; } @Override public void run() { try { System.out.println(machineName + "开始采集"); Thread.sleep(spendTime); } catch (InterruptedException e) { e.printStackTrace(); } }}
在ThreadJoin
的代码中,我们创建了主线程main
,和实现了Runnable
的CaptureRunnable
子线程,运行main
方法,可以看到在未使用join()
的情况下,统计结果并不理想,正确输出应该是5000毫秒以上
采集完成,消耗 1M1开始采集M2开始采集M3开始采集
使用join
在start
方法下添加join
操作,运行main
方法,发现不管那个线程先执行,结果都是5000毫秒以上
,因为主线程main
接收到了M1,M2,M3
三个线程的join
指令,这个时候主线程
则会处于阻塞状态,直到子线程
执行完毕后才会继续执行下去…
t1.start();t2.start();t3.start();t1.join();t2.join();t3.join();
M2开始采集M1开始采集M3开始采集采集完成,消耗 5001
部分join
去掉M1
线程调用的join
,然后运行main
方法,从日志输出中可以发现,main
会等待M2,M3
执行完毕后才会继续执行下去
M1开始采集M3开始采集M2开始采集采集完成,消耗 3001
源码分析
public final void join() throws InterruptedException { join(0);}public final synchronized void join(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()) { wait(0); } } else { while (isAlive()) { long delay = millis - now; if (delay <= 0) { break; } wait(delay); now = System.currentTimeMillis() - base; } }}
说明
从代码中,我们可以发现。当millis==0
时,会进入while(isAlive())
循环,系统会判断主线程
是否处于活跃状态,如果处于活跃状态,主线程
就会不停的等待。
问题
为什么子线程
调用join()
阻塞的却是主线程呢?join()
方法中的isAlive()
应该是判断子线程
是否处于活跃的状态,对应的wait(0)
也应该是让子线程
等待才对
答案
首先从源码中我们可以发现它是被synchronized
修饰的方法,当前线程的对象调用join
后,其实获取到了子线程M1,M2,M3
的锁,当子线程锁释放后才会继续执行主线程
的操作
使用jvisualvm
分析器,可以发现Thread-1-3
与主线程main
,处于等待的是主线程
,子线程因为调用了sleep
处于休眠状态(为了演示耗时操作)
- 说点什么
全文代码:https://git.oschina.net/battcn/battcn-concurent/tree/master/Chapter1-1/battcn-thread/src/main/java/com/battcn/chapter3
- 个人QQ:1837307557
- battcn开源群(适合新手):391619659
微信公众号:battcn
(欢迎调戏)
- 一起学并发编程
- 一起学并发编程
- 一起学并发编程
- 一起学并发编程
- 一起学并发编程
- 一起学并发编程
- 一起学并发编程
- 一起学并发编程
- 一起学并发编程
- 一起学并发编程
- 一起学并发编程
- 一起学编程(1)
- 看动画学并发编程
- 看动画学并发编程
- 面向方面编程,有兴趣的一起学
- 《与孩子一起学编程》译者序
- 《与孩子一起学编程》书评
- 与孩子一起学编程1
- MFC DLL
- NYOJ 649 Books
- SVN服务器搭建和使用(二)
- Angular路由
- Thinker热修复
- 一起学并发编程
- Spring Cloud Bus之RabbitMQ初窥
- PHP 安装 Pthreads (解决 class Thread not found )
- Java设计模式百例
- .gitignore规则和忽略已经被git管理的文件
- win10环境下JDK的安装
- 一起学并发编程
- 数字三角形 hiho一下第 5 周
- OpenGL模型视图变换