Java Thread.join()详解(转)
(1)join方法是可以中断的
(2)在线程joiner在另一个线程t上调用t.join(),线程joiner将被挂起,直到线程t结束(即t.isAlive()返回为false)才恢复
package thread.join2; class Sleeper extends Thread{
private int duration;
public Sleeper(String name,int sleepTime) {
super(name);
duration=sleepTime;
start();
}
@Override
public void run() {
try {
sleep(duration);
} catch (InterruptedException e) {
System.out.println(currentThread()+" was interrupted. isInterrupted():"+isInterrupted());
return;
}
System.out.println(currentThread()+" was awakened");
}
} class Joiner extends Thread{
private Sleeper sleeper;
public Joiner(String name,Sleeper sleeper) {
super(name);
this.sleeper=sleeper;
start();
} @Override
public void run() {
try {
sleeper.join();
} catch (InterruptedException e) {
System.out.println(currentThread()+" Interrupted.");
}
System.out.println(currentThread()+" join completed.");
} } public class JoinTest { public static void main(String[] args) {
int sleepTime=1500;
Sleeper sleepy_sleeper=new Sleeper("sleepy_sleeper", sleepTime);
Sleeper grumpy_sleeper=new Sleeper("grumpy_sleeper", sleepTime); Joiner dopey_joiner=new Joiner("dopey_joiner", sleepy_sleeper);
Joiner doc_joiner=new Joiner("doc_joiner", grumpy_sleeper);
grumpy_sleeper.interrupt();
} }
Output:
Thread[grumpy_sleeper,5,main] was interrupted. isInterrupted():false
Thread[doc_joiner,5,main] join completed.
Thread[sleepy_sleeper,5,main] was awakened
Thread[dopey_joiner,5,main] join completed.
一、使用方式。
join是Thread类的一个方法,启动线程后直接调用,例如:
1
|
Thread t = new AThread(); t.start(); t.join(); |
二、为什么要用join()方法
在很多情况下,主线程生成并起动了子线程,如果子线程里要进行大量的耗时的运算,主线程往往将于子线程之前结束,但是如果主线程处理完其他的事务后,需要用到子线程的处理结果,也就是主线程需要等待子线程执行完成之后再结束,这个时候就要用到join()方法了。
三、join方法的作用
在JDk的API里对于join()方法是:
join
public final void join() throws InterruptedException Waits for this thread to die. Throws: InterruptedException - if any thread has interrupted the current thread. The interrupted status of the current thread is cleared when this exception is thrown.
即join()的作用是:“等待该线程终止”,这里需要理解的就是该线程是指的主线程等待子线程的终止。也就是在子线程调用了join()方法后面的代码,只有等到子线程结束了才能执行。
四、用实例来理解
写一个简单的例子来看一下join()的用法:
1.AThread 类
BThread类
TestDemo 类
12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152class
BThread
extends
Thread {
public
BThread() {
super
(
"[BThread] Thread"
);
};
public
void
run() {
String threadName = Thread.currentThread().getName();
System.out.println(threadName +
" start."
);
try
{
for
(
int
i =
0
; i <
5
; i++) {
System.out.println(threadName +
" loop at "
+ i);
Thread.sleep(
1000
);
}
System.out.println(threadName +
" end."
);
}
catch
(Exception e) {
System.out.println(
"Exception from "
+ threadName +
".run"
);
}
}
}
class
AThread
extends
Thread {
BThread bt;
public
AThread(BThread bt) {
super
(
"[AThread] Thread"
);
this
.bt = bt;
}
public
void
run() {
String threadName = Thread.currentThread().getName();
System.out.println(threadName +
" start."
);
try
{
bt.join();
System.out.println(threadName +
" end."
);
}
catch
(Exception e) {
System.out.println(
"Exception from "
+ threadName +
".run"
);
}
}
}
public
class
TestDemo {
public
static
void
main(String[] args) {
String threadName = Thread.currentThread().getName();
System.out.println(threadName +
" start."
);
BThread bt =
new
BThread();
AThread at =
new
AThread(bt);
try
{
bt.start();
Thread.sleep(
2000
);
at.start();
at.join();
}
catch
(Exception e) {
System.out.println(
"Exception from main"
);
}
System.out.println(threadName +
" end!"
);
}
}
打印结果:
1234567891011main start.
//
主线程起动,因为调用了at.
join
(),要等到at结束了,此线程才能向下执行。
[BThread] Thread start.
[BThread] Thread loop at 0
[BThread] Thread loop at 1
[AThread] Thread start.
//
线程at启动,因为调用bt.
join
(),等到bt结束了才向下执行。
[BThread] Thread loop at 2
[BThread] Thread loop at 3
[BThread] Thread loop at 4
[BThread] Thread end.
[AThread] Thread end.
//
线程AThread在bt.
join
();阻塞处起动,向下继续执行的结果
main end!
//
线程AThread结束,此线程在at.
join
();阻塞处起动,向下继续执行的结果。
修改一下代码:
1234567891011121314151617public
class
TestDemo {
public
static
void
main(String[] args) {
String threadName = Thread.currentThread().getName();
System.out.println(threadName +
" start."
);
BThread bt =
new
BThread();
AThread at =
new
AThread(bt);
try
{
bt.start();
Thread.sleep(
2000
);
at.start();
//at.join(); //在此处注释掉对join()的调用
}
catch
(Exception e) {
System.out.println(
"Exception from main"
);
}
System.out.println(threadName +
" end!"
);
}
}
打印结果:
123456789101112main start.
//
主线程起动,因为Thread.
sleep
(2000),主线程没有马上结束;
[BThread] Thread start.
//
线程BThread起动
[BThread] Thread loop at 0
[BThread] Thread loop at 1
main end!
//
在
sleep
两秒后主线程结束,AThread执行的bt.
join
();并不会影响到主线程。
[AThread] Thread start.
//
线程at起动,因为调用了bt.
join
(),等到bt结束了,此线程才向下执行。
[BThread] Thread loop at 2
[BThread] Thread loop at 3
[BThread] Thread loop at 4
[BThread] Thread end.
//
线程BThread结束了
[AThread] Thread end.
//
线程AThread在bt.
join
();阻塞处起动,向下继续执行的结果
五、从源码看join()方法
在AThread的run方法里,执行了bt.join();,进入看一下它的JDK源码:
123public
final
void
join()
throws
InterruptedException {
join(0L);
}
然后进入join(0L)方法:
123456789101112131415161718192021public
final
synchronized
void
join(
long
l)
throws
InterruptedException
{
long
l1 = System.currentTimeMillis();
long
l2 = 0L;
if
(l < 0L)
throw
new
IllegalArgumentException(
"timeout value is negative"
);
if
(l == 0L)
for
(; isAlive(); wait(0L));
else
do
{
if
(!isAlive())
break
;
long
l3 = l - l2;
if
(l3 <= 0L)
break
;
wait(l3);
l2 = System.currentTimeMillis() - l1;
}
while
(
true
);
}
单纯从代码上看: * 如果线程被生成了,但还未被起动,isAlive()将返回false,调用它的join()方法是没有作用的。将直接继续向下执行。 * 在AThread类中的run方法中,bt.join()是判断bt的active状态,如果bt的isActive()方法返回false,在bt.join(),这一点就不用阻塞了,可以继续向下进行了。从源码里看,wait方法中有参数,也就是不用唤醒谁,只是不再执行wait,向下继续执行而已。 * 在join()方法中,对于isAlive()和wait()方法的作用对象是个比较让人困惑的问题:
isAlive()方法的签名是:public final native boolean isAlive(),也就是说isAlive()是判断当前线程的状态,也就是bt的状态。
wait()方法在jdk文档中的解释如下:
Causes the current thread to wait until another thread invokes the notify() method or the notifyAll() method for this object. In other words, this method behaves exactly as if it simply performs the call wait(0).
The current thread must own this object's monitor. The thread releases ownership of this monitor and waits until another thread notifies threads waiting on this object's monitor to wake up either through a call to the notify method or the notifyAll method. The thread then waits until it can re-obtain ownership of the monitor and resumes execution.
在这里,当前线程指的是at。
http://www.open-open.com/lib/view/open1371741636171.html
Java Thread.join()详解(转)的更多相关文章
- 【转】Java Thread.join()详解
http://www.open-open.com/lib/view/open1371741636171.html 一.使用方式. join是Thread类的一个方法,启动线程后直接调用,例如: ? 1 ...
- Java Thread.join()详解--父线程等待子线程结束后再结束
目录(?)[+] 阅读目录 一.使用方式. 二.为什么要用join()方法 三.join方法的作用 join 四.用实例来理解 打印结果: 打印结果: 五.从源码看join()方法 join是Th ...
- Java Thread.join()详解
一.使用方式. 二.为什么要用join()方法 三.join方法的作用 join 四.用实例来理解 打印结果: 打印结果: 五.从源码看join()方法 一.使用方式. join是Thread类的 ...
- Java Thread.yield详解
这是Java中的一种线程让步方法,让Java中的线程从执行状态变成就绪状态,然后处理器再从就绪队列中挑选线程进行执行(优先级大的,被挑选的概率较大),这种转换也不确定,让或者不让都是取决与处理器,线程 ...
- Thread.join详解
/** * 如果某个线程在另一个线程t上调用t.join:那么此线程将被挂起,直到目标t线程的结束才恢复即t.isAlive返回为假 * * @date:2018年6月27日 * @author:zh ...
- [译]Java Thread join示例与详解
Java Thread join示例与详解 Java Thread join方法用来暂停当前线程直到join操作上的线程结束.java中有三个重载的join方法: public final void ...
- Java基础-进程与线程之Thread类详解
Java基础-进程与线程之Thread类详解 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. 一.进程与线程的区别 简而言之:一个程序运行后至少有一个进程,一个进程中可以包含多个线程 ...
- java.lang.Thread类详解
java.lang.Thread类详解 一.前言 位于java.lang包下的Thread类是非常重要的线程类,它实现了Runnable接口,今天我们来学习一下Thread类,在学习Thread类之前 ...
- Java线程创建形式 Thread构造详解 多线程中篇(五)
Thread作为线程的抽象,Thread的实例用于描述线程,对线程的操纵,就是对Thread实例对象的管理与控制. 创建一个线程这个问题,也就转换为如何构造一个正确的Thread对象. 构造方法列表 ...
随机推荐
- 用CentOS,fedora等访问局域网中的Windows共享
来到Linux世界中已有一段时间了,感觉上好像自己的电脑成了一个孤岛.周围的人都还是用Windows系统,能相互共享文件,我用Linux系统,别人的共享文件都还不知道怎么访问?通过网上查资料学习,现在 ...
- H3C HCSE 官方培训胶片(中文) 下载
H3C HCSE 官方培训胶片(中文) 点击文件名下载 HM-040 OSPF路由协议(V5.1).ppt HM-041 BGP协议原理及配置(V5.0).ppt HM-041 BGP协议原理及配置( ...
- Machine Learning #Lab1# Linear Regression
Machine Learning Lab1 打算把Andrew Ng教授的#Machine Learning#相关的6个实验一一实现了贴出来- 预计时间长度战线会拉的比較长(毕竟JOS的7级浮屠还没搞 ...
- JNI 详细解释
JNI事实上,Java Native Interface缩写,那是,java本地接口.它提供了许多API实现和Java和其它语言的通信(主要是C&C++). 或许不少人认为Java已经足够强大 ...
- stm32智能小车之路之小车启动
首先.安装完小车后最激动的还是想让他跑动,那么就開始吧.写个简单的程序測试下电机是否正常.打开keil软件新建一个project,详细简历keilproject不会的请百度.或者call ...
- Nodejs 项目开发
最近这几个月都在学习nodejs. 国内nodejs的资料相对较少,就我所搜索到的,CSDN目前的代码托管平台有不少从github弄过来的开源镜像,其它的不错的社区有cnodejs,byvoid的个人 ...
- DOM方法入门 - 第二课
1.console.log()是吧元素显示在控制台2.appendChild() 就是将元素追加到末尾3.innerHTML获取的是元素里面的所有内容包括里面的子元素4.innerText获取的是元素 ...
- spark中各种连接操作以及有用方法
val a = sc.parallelize(Array(("123",4.0),("456",9.0),("789",9.0)) val ...
- extjs_04_grid(弹出窗口&行编辑器 CRUD数据)
1.弹出窗口(添加.删除) watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvYWRhbV93enM=/font/5a6L5L2T/fontsize/400/f ...
- android https通过载入pfx证书获取数据
直接给代码吧.研究了几天才搞定...... public static final String CLIENT_KET_PASSWORD = "Ku6OpqKDfN4=305790" ...