java线程研究---(6)暂停Thread:join
2015-08-25 17:04
501 查看
暂停Thread
join方法,会让线程线程暂停,具体如下:
调用方法:Thread对象.join()
比如,当前有一个线程对象son,当调用了son.join()方法之后(不是child.start()方法哦),
会让线程对象son的父级线程对象mother,从执行(running)状态进入暂停(blocked)状态。
并且mother线程对象,会获取到线程对象son的执行完毕时刻,再从暂停(blocked)状态,进入等待执行(runnable)状态
所以join方法的使用场景是:
有两个线程对象mother和son
mother线程对象先开始执行,在执行期间,希望让son线程对象执行,
在调用son.join()之后,mother线程对象进入暂停状态等待son线程对象执行完毕,
当son线程对象执行完毕之后,mother线程对象会被通知,继续执行,
mother对象线程执行完毕。
先来温习一下状态图吧:
-----------------------------------------------------------------------------------------------------------------------------测试1:
测试场景如下:
妈妈(MotherThread)准备炒菜
发现没有酱油,就让儿子(SonThread)去买回来
期间妈妈一直在等待儿子归来
儿子买回来之后,妈妈开始继续炒菜。
测试代码如下:
MotherThread.java
SonThread.java
Cooking.java
打印结果:
妈妈准备炒菜
妈妈发现没有酱油
妈妈让儿子去买酱油
儿子开始买酱油
买酱油需要5分钟:
过去1分钟, 过去2分钟, 过去3分钟, 过去4分钟, 过去5分钟,
儿子买酱油回来了!
妈妈开始炒菜
菜炒完毕了~~~
-----------------------------------------------------------------------------------------------------------------------------测试2:
这里的例子,我主要想强调一下。
调用son.start()之后,mother线程并不是暂停的,mother线程其实是和son线程并行执行的(比如,mother在让son去买酱油之后,可以去看电视或上厕所)。
(之前的例子,只不过在调用son.start()之后,马上又调用son.join()方法了。所以给大家的感觉是,son在去买酱油之后,mother啥都不能干,只能等待。。。)
注意,
只有在调用son.join()之后,mother线程才“等待”son线程执行完毕,
在调用son.join()之前,mother可以干其他的事情
但是mother这个“等待”时间或者长或短,为什么说呢:
mother线程(在调用son.start()方法之后)和son线程既然并行的,
那么这两个线程就有执行时间长短不同的问题:
son线程执行时间长,mother线程(在调用son.start()方法之后)执行时间短:
son买酱油需要10分钟,同时mother看了5分钟的电视
看了5分钟电视之后,才调用son.join(),那么mother就再等5分钟,儿子买酱油回来
mother线程(在调用son.start()方法之后)执行时间长,son线程执行时间短:
son买酱油需要5分钟,同时mother看10分钟的电视
看了10分钟电视之后,才调用son.join(),那么mother不需要等待son执行完毕,
因为son线程已经执行完毕了——儿子已经5分钟买酱油回来了,只不过一直在门外敲门
子线程执行时间长(son10分钟),主线程执行时间短(mother5分钟)测试场景如下:----------------------------------------------
妈妈(MotherThread)准备炒菜
发现没有酱油,就让儿子(SonThread)去买回来----需要10分钟
期间妈妈一直在看电视-------看5分钟
看完5分钟电视之后,妈妈没干别的事情,只是焦急的等待儿子回来。
等了5分钟之后,儿子买酱油回来
妈妈开始继续炒菜。
测试代码如下:
MotherThread.java
SonThread.java
控制台效果:
妈妈准备炒菜
妈妈发现没有酱油
妈妈让儿子去买酱油
儿子买酱油的同时,妈妈开始看5分钟电视:
儿子开始买酱油,买酱油需要10分钟:
妈妈看电视,过去1分钟,
儿子买酱油,过去1分钟,
妈妈看电视,过去2分钟,
儿子买酱油,过去2分钟,
妈妈看电视,过去3分钟,
儿子买酱油,过去3分钟,
妈妈看电视,过去4分钟,
儿子买酱油,过去4分钟,
妈妈看电视,过去5分钟,
看完电视,5分钟过去了,妈妈焦急的等待儿子回来。
儿子买酱油,过去5分钟,
儿子买酱油,过去6分钟,
儿子买酱油,过去7分钟,
儿子买酱油,过去8分钟,
儿子买酱油,过去9分钟,
儿子买酱油,过去10分钟,
儿子买酱油回来了,等待妈妈开门
妈妈开门,拿到酱油
妈妈开始炒菜
菜炒完毕了~~~
主线程执行时间长(mother10分钟),子线程执行时间短(son5分钟)测试场景如下:----------------------------------------------
妈妈(MotherThread)准备炒菜
发现没有酱油,就让儿子(SonThread)去买回来----需要5分钟
期间妈妈一直在看电视-------看10分钟
儿子过了5分钟之后买回来,在门外敲门,等待妈妈开门
此时妈妈才看了5分钟的电视
又过了5分钟之后,妈妈看完电视,才给儿子开门,拿到酱油
妈妈开始继续炒菜。
测试代码如下:
MotherThread.java
SonThread.java
控制台效果:
Thread-0------>妈妈准备炒菜
Thread-0------>妈妈发现没有酱油
Thread-0------>妈妈让儿子去买酱油
Thread-0------>儿子买酱油的同时,妈妈开始看10分钟电视:
Thread-1------>儿子开始买酱油,买酱油需要5分钟:
Thread-0------>son thread is alive:true
Thread-1------>儿子买酱油,过去1分钟,
Thread-0------>妈妈看电视,过去1分钟,
Thread-1------>儿子买酱油,过去2分钟,
Thread-0------>son thread is alive:true
Thread-0------>妈妈看电视,过去2分钟,
Thread-1------>儿子买酱油,过去3分钟,
Thread-0------>son thread is alive:true
Thread-0------>妈妈看电视,过去3分钟,
Thread-1------>儿子买酱油,过去4分钟,
Thread-0------>son thread is alive:true
Thread-0------>妈妈看电视,过去4分钟,
Thread-0------>son thread is alive:true
Thread-1------>儿子买酱油,过去5分钟,
Thread-0------>妈妈看电视,过去5分钟,
Thread-1------>儿子买酱油回来了,等待妈妈开门
Thread-0------>son thread is alive:false
Thread-0------>妈妈看电视,过去6分钟,
Thread-0------>son thread is alive:false
Thread-0------>妈妈看电视,过去7分钟,
Thread-0------>son thread is alive:false
Thread-0------>妈妈看电视,过去8分钟,
Thread-0------>son thread is alive:false
Thread-0------>妈妈看电视,过去9分钟,
Thread-0------>son thread is alive:false
Thread-0------>妈妈看电视,过去10分钟,
Thread-0------>看完电视,10分钟过去了,妈妈才想起来,儿子应该5分钟前就已经回来了。
Thread-0------>妈妈开门,拿到酱油
Thread-0------>妈妈开始炒菜
Thread-0------>菜炒完毕了~~~
希望大家能够通过测试2的这两个例子,能对join方法有一个深刻的体会。
另外join方法还可以穿入参数!怎么理解?我的如下理解
:
妈妈让儿子去买酱油(儿子买酱油期间,妈妈想干啥都可以,跟join方法不发生关系)
妈妈假定了儿子去买酱油需要10分钟:son.join(10*1000)
如果10分钟之后,儿子还没有买回来酱油。
妈妈就不等了,不用酱油继续炒菜!
如果10分钟之内!儿子买回来酱油。
妈妈用酱油,继续炒菜!
注意,我例子里面的分钟,其实就是代码里面的秒啦
join方法,会让线程线程暂停,具体如下:
调用方法:Thread对象.join()
比如,当前有一个线程对象son,当调用了son.join()方法之后(不是child.start()方法哦),
会让线程对象son的父级线程对象mother,从执行(running)状态进入暂停(blocked)状态。
并且mother线程对象,会获取到线程对象son的执行完毕时刻,再从暂停(blocked)状态,进入等待执行(runnable)状态
所以join方法的使用场景是:
有两个线程对象mother和son
mother线程对象先开始执行,在执行期间,希望让son线程对象执行,
在调用son.join()之后,mother线程对象进入暂停状态等待son线程对象执行完毕,
当son线程对象执行完毕之后,mother线程对象会被通知,继续执行,
mother对象线程执行完毕。
先来温习一下状态图吧:
-----------------------------------------------------------------------------------------------------------------------------测试1:
测试场景如下:
妈妈(MotherThread)准备炒菜
发现没有酱油,就让儿子(SonThread)去买回来
期间妈妈一直在等待儿子归来
儿子买回来之后,妈妈开始继续炒菜。
测试代码如下:
MotherThread.java
package thread; public class MotherThread implements Runnable { @Override public void run() { System.out.println("妈妈准备炒菜"); try { Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println("妈妈发现没有酱油"); System.out.println("妈妈让儿子去买酱油"); Thread son = new Thread(new SonThread()); son.start(); try { son.join(); // 这里MotherThread线程对象,进入暂停,并且让MotherThread线程,获取SonThread线程执行完毕的时刻 } catch (InterruptedException e) { System.err.println("儿子发生异常!妈妈中断炒菜"); System.exit(1); } System.out.println("妈妈开始炒菜"); System.out.println("菜炒完毕了~~~"); } }
SonThread.java
package thread; public class SonThread implements Runnable { public void run() { System.out.println("儿子开始买酱油"); System.out.println("买酱油需要5分钟:"); try { for (int i = 1; i <= 5; i++) { Thread.sleep(1000); System.out.print("过去" + i + "分钟, "); } } catch (InterruptedException e) { System.err.println("儿子发生意外"); } System.out.println(""); System.out.println("儿子买酱油回来了!"); } }
Cooking.java
package thread; public class Cooking { public static void main(String abc[]) { Thread mother = new Thread(new MotherThread()); mother.start(); } }
打印结果:
妈妈准备炒菜
妈妈发现没有酱油
妈妈让儿子去买酱油
儿子开始买酱油
买酱油需要5分钟:
过去1分钟, 过去2分钟, 过去3分钟, 过去4分钟, 过去5分钟,
儿子买酱油回来了!
妈妈开始炒菜
菜炒完毕了~~~
-----------------------------------------------------------------------------------------------------------------------------测试2:
这里的例子,我主要想强调一下。
调用son.start()之后,mother线程并不是暂停的,mother线程其实是和son线程并行执行的(比如,mother在让son去买酱油之后,可以去看电视或上厕所)。
(之前的例子,只不过在调用son.start()之后,马上又调用son.join()方法了。所以给大家的感觉是,son在去买酱油之后,mother啥都不能干,只能等待。。。)
注意,
只有在调用son.join()之后,mother线程才“等待”son线程执行完毕,
在调用son.join()之前,mother可以干其他的事情
但是mother这个“等待”时间或者长或短,为什么说呢:
mother线程(在调用son.start()方法之后)和son线程既然并行的,
那么这两个线程就有执行时间长短不同的问题:
son线程执行时间长,mother线程(在调用son.start()方法之后)执行时间短:
son买酱油需要10分钟,同时mother看了5分钟的电视
看了5分钟电视之后,才调用son.join(),那么mother就再等5分钟,儿子买酱油回来
mother线程(在调用son.start()方法之后)执行时间长,son线程执行时间短:
son买酱油需要5分钟,同时mother看10分钟的电视
看了10分钟电视之后,才调用son.join(),那么mother不需要等待son执行完毕,
因为son线程已经执行完毕了——儿子已经5分钟买酱油回来了,只不过一直在门外敲门
子线程执行时间长(son10分钟),主线程执行时间短(mother5分钟)测试场景如下:----------------------------------------------
妈妈(MotherThread)准备炒菜
发现没有酱油,就让儿子(SonThread)去买回来----需要10分钟
期间妈妈一直在看电视-------看5分钟
看完5分钟电视之后,妈妈没干别的事情,只是焦急的等待儿子回来。
等了5分钟之后,儿子买酱油回来
妈妈开始继续炒菜。
测试代码如下:
MotherThread.java
package thread; public class MotherThread implements Runnable { @Override public void run() { // 是否儿子去买酱油 boolean buySoy = false; // 是否看电视 boolean watchTV = false; System.out.println("妈妈准备炒菜"); try { Thread.sleep(1000); // 炒菜持续一分钟之后 } catch (InterruptedException e) { e.printStackTrace(); } System.out.println("妈妈发现没有酱油"); buySoy = true; // 儿子去买酱油 watchTV = true; // 买酱油期间,看电视 Thread son = new Thread(new SonThread()); if (buySoy) { System.out.println("妈妈让儿子去买酱油"); son.start(); } if (watchTV) { // 儿子买酱油的同时,妈妈开始看5分钟电视 System.out.println("儿子买酱油的同时,妈妈开始看5分钟电视:"); try { for (int i = 1; i <= 5; i++) { Thread.sleep(1000); //这里用sleep时间代表看电视 System.out.println("妈妈看电视,过去" + i + "分钟, "); } } catch (InterruptedException e) { e.printStackTrace(); } } try { System.out.println("看完电视,5分钟过去了,妈妈焦急的等待儿子回来。"); son.join(); System.out.println("妈妈开门,拿到酱油"); } catch (InterruptedException e) { System.err.println("儿子发生异常!妈妈中断炒菜"); System.exit(1); } System.out.println("妈妈开始炒菜"); System.out.println("菜炒完毕了~~~"); } }
SonThread.java
package thread; public class SonThread implements Runnable { public void run() { System.out.println("儿子开始买酱油,买酱油需要10分钟:"); try { for (int i = 1; i <= 10; i++) { Thread.sleep(1000); //这里用sleep时间代表买酱油 System.out.println("儿子买酱油,过去" + i + "分钟, "); } } catch (InterruptedException e) { System.err.println("儿子发生意外"); } System.out.println("儿子买酱油回来了,等待妈妈开门"); } }
控制台效果:
妈妈准备炒菜
妈妈发现没有酱油
妈妈让儿子去买酱油
儿子买酱油的同时,妈妈开始看5分钟电视:
儿子开始买酱油,买酱油需要10分钟:
妈妈看电视,过去1分钟,
儿子买酱油,过去1分钟,
妈妈看电视,过去2分钟,
儿子买酱油,过去2分钟,
妈妈看电视,过去3分钟,
儿子买酱油,过去3分钟,
妈妈看电视,过去4分钟,
儿子买酱油,过去4分钟,
妈妈看电视,过去5分钟,
看完电视,5分钟过去了,妈妈焦急的等待儿子回来。
儿子买酱油,过去5分钟,
儿子买酱油,过去6分钟,
儿子买酱油,过去7分钟,
儿子买酱油,过去8分钟,
儿子买酱油,过去9分钟,
儿子买酱油,过去10分钟,
儿子买酱油回来了,等待妈妈开门
妈妈开门,拿到酱油
妈妈开始炒菜
菜炒完毕了~~~
主线程执行时间长(mother10分钟),子线程执行时间短(son5分钟)测试场景如下:----------------------------------------------
妈妈(MotherThread)准备炒菜
发现没有酱油,就让儿子(SonThread)去买回来----需要5分钟
期间妈妈一直在看电视-------看10分钟
儿子过了5分钟之后买回来,在门外敲门,等待妈妈开门
此时妈妈才看了5分钟的电视
又过了5分钟之后,妈妈看完电视,才给儿子开门,拿到酱油
妈妈开始继续炒菜。
测试代码如下:
MotherThread.java
package thread; public class MotherThread implements Runnable { @Override public void run() { String threadName = Thread.currentThread().getName()+"------>"; // 是否儿子去买酱油 boolean buySoy = false; // 是否看电视 boolean watchTV = false; System.out.println(threadName+"妈妈准备炒菜"); try { Thread.sleep(1000); // 炒菜持续一分钟之后 } catch (InterruptedException e) { e.printStackTrace(); } System.out.println(threadName+"妈妈发现没有酱油"); buySoy = true; // 儿子去买酱油 watchTV = true; // 买酱油期间,看电视 Thread son = new Thread(new SonThread()); if (buySoy) { System.out.println(threadName+"妈妈让儿子去买酱油"); son.start(); } if (watchTV) { // 儿子买酱油的同时,妈妈开始看10分钟电视 System.out.println(threadName+"儿子买酱油的同时,妈妈开始看10分钟电视:"); try { for (int i = 1; i <= 10; i++) { Thread.sleep(1000); //这里用sleep时间代表看电视 System.out.println(threadName+"son thread is alive:"+ son.isAlive()); //观察son线程是否已经进入死亡状态 System.out.println(threadName+"妈妈看电视,过去" + i + "分钟, "); } } catch (InterruptedException e) { e.printStackTrace(); } } try { System.out.println(threadName+"看完电视,10分钟过去了,妈妈才想起来,儿子应该5分钟前就已经回来了。"); son.join(); System.out.println(threadName+"妈妈开门,拿到酱油"); } catch (InterruptedException e) { System.err.println(threadName+"儿子发生异常!妈妈中断炒菜"); System.exit(1); } System.out.println(threadName+"妈妈开始炒菜"); System.out.println(threadName+"菜炒完毕了~~~"); } }
SonThread.java
package thread; public class SonThread implements Runnable { public void run() { String threadName = Thread.currentThread().getName()+"------>"; System.out.println(threadName+"儿子开始买酱油,买酱油需要5分钟:"); try { for (int i = 1; i <= 5; i++) { Thread.sleep(1000); //这里用sleep时间代表买酱油 System.out.println(threadName+"儿子买酱油,过去" + i + "分钟, "); } } catch (InterruptedException e) { System.err.println(threadName+"儿子发生意外"); } System.out.println(threadName+"儿子买酱油回来了,等待妈妈开门"); } }
控制台效果:
Thread-0------>妈妈准备炒菜
Thread-0------>妈妈发现没有酱油
Thread-0------>妈妈让儿子去买酱油
Thread-0------>儿子买酱油的同时,妈妈开始看10分钟电视:
Thread-1------>儿子开始买酱油,买酱油需要5分钟:
Thread-0------>son thread is alive:true
Thread-1------>儿子买酱油,过去1分钟,
Thread-0------>妈妈看电视,过去1分钟,
Thread-1------>儿子买酱油,过去2分钟,
Thread-0------>son thread is alive:true
Thread-0------>妈妈看电视,过去2分钟,
Thread-1------>儿子买酱油,过去3分钟,
Thread-0------>son thread is alive:true
Thread-0------>妈妈看电视,过去3分钟,
Thread-1------>儿子买酱油,过去4分钟,
Thread-0------>son thread is alive:true
Thread-0------>妈妈看电视,过去4分钟,
Thread-0------>son thread is alive:true
Thread-1------>儿子买酱油,过去5分钟,
Thread-0------>妈妈看电视,过去5分钟,
Thread-1------>儿子买酱油回来了,等待妈妈开门
Thread-0------>son thread is alive:false
Thread-0------>妈妈看电视,过去6分钟,
Thread-0------>son thread is alive:false
Thread-0------>妈妈看电视,过去7分钟,
Thread-0------>son thread is alive:false
Thread-0------>妈妈看电视,过去8分钟,
Thread-0------>son thread is alive:false
Thread-0------>妈妈看电视,过去9分钟,
Thread-0------>son thread is alive:false
Thread-0------>妈妈看电视,过去10分钟,
Thread-0------>看完电视,10分钟过去了,妈妈才想起来,儿子应该5分钟前就已经回来了。
Thread-0------>妈妈开门,拿到酱油
Thread-0------>妈妈开始炒菜
Thread-0------>菜炒完毕了~~~
希望大家能够通过测试2的这两个例子,能对join方法有一个深刻的体会。
另外join方法还可以穿入参数!怎么理解?我的如下理解
:
妈妈让儿子去买酱油(儿子买酱油期间,妈妈想干啥都可以,跟join方法不发生关系)
妈妈假定了儿子去买酱油需要10分钟:son.join(10*1000)
如果10分钟之后,儿子还没有买回来酱油。
妈妈就不等了,不用酱油继续炒菜!
如果10分钟之内!儿子买回来酱油。
妈妈用酱油,继续炒菜!
注意,我例子里面的分钟,其实就是代码里面的秒啦
相关文章推荐
- Java知识总结----日志系统在项目中的应用(五)
- IDEA工具类似Eclipse中Ctrl+O查找当前类中方法的快捷键
- java socket编程学习笔记
- Java多线程之二
- JAVA问题总结之7--Pow、sin、sqrt、abs等常用数学函数调用
- SpringDataJPA入门2
- java动态JSON数据解析
- Java反射机制
- 使用 Eclipse 插件提高代码质量,让开发自动化。
- Struts2_2_第一Struts2应用
- JavaMail发送邮件
- Java笔记——JavaMail发送邮件
- Eclipse快捷键使用解说
- 理解Java之泛型
- Introduction to Java Programming编程题9.9<二进制转十六进制>
- Java String的关键点
- java集群技术
- 利用Spring将配置文件读入Map
- Eclipse常见设置及快捷键使用总结(更新中)
- hdu3887 Counting Offspring(dfs序+树状数组)