简谈Java的join()方法
join()是Thread类的一个方法。根据jdk文档的定义:
public final void join()throws InterruptedException: Waits for this thread to die.
join()方法的作用,是等待这个线程结束;但显然,这样的定义并不清晰。个人认为"Java 7 Concurrency Cookbook"的定义较为清晰:
join() method suspends the execution of the calling thread until the object called finishes its execution.
也就是说,t.join()方法阻塞调用此方法的线程(calling thread),直到线程t完成,此线程再继续;通常用于在main()主线程内,等待其它线程完成再结束main()主线程。例如:
public class JoinTester01 implements Runnable { private String name; public JoinTester01(String name) {
this.name = name;
} public void run() {
System.out.printf("%s begins: %s\n", name, new Date());
try {
TimeUnit.SECONDS.sleep(4);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.printf("%s has finished: %s\n", name, new Date());
} public static void main(String[] args) {
Thread thread1 = new Thread(new JoinTester01("One"));
Thread thread2 = new Thread(new JoinTester01("Two"));
thread1.start();
thread2.start(); try {
thread1.join();
thread2.join();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} System.out.println("Main thread is finished");
} }
上述代码如果没有join()方法,输出如下:
Main thread is finished
One begins: Wed Aug 28 10:21:36 CST 2013
Two begins: Wed Aug 28 10:21:36 CST 2013
Two has finished: Wed Aug 28 10:21:40 CST 2013
One has finished: Wed Aug 28 10:21:40 CST 2013
可以看出主线程main比其它两个线程先结束。
最后来深入了解一下join(),请看其源码:
/**
* Waits at most <code>millis</code> milliseconds for this thread to
* die. A timeout of <code>0</code> means to wait forever.
*/
//此处A timeout of 0 means to wait forever 字面意思是永远等待,其实是等到t结束后。
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;
}
}
}
可以看出,Join方法实现是通过wait(小提示:Object 提供的方法)。 当main线程调用t.join时候,main线程会获得线程对象t的锁(wait 意味着拿到该对象的锁),调用该对象的wait(等待时间),直到该对象唤醒main线程 ,比如退出后。这就意味着main 线程调用t.join时,必须能够拿到线程t对象的锁。
public class JoinTester02 implements Runnable { Thread thread; public JoinTester02(Thread thread) {
this.thread = thread;
} public void run() {
synchronized (thread) {
System.out.println("getObjectLock");
try {
Thread.sleep(9000);
} catch (InterruptedException ex) {
ex.printStackTrace();
}
System.out.println("ReleaseObjectLock");
}
} public static void main(String[] args) {
Thread thread = new Thread(new JoinTester01("Three"));
Thread getLockThread = new Thread(new JoinTester02(thread)); getLockThread.start();
thread.start(); try {
thread.join();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
System.out.println("Main finished!");
} }public class JoinTester02 implements Runnable { Thread thread; public JoinTester02(Thread thread) {
this.thread = thread;
} public void run() {
synchronized (thread) {
System.out.println("getObjectLock");
try {
Thread.sleep(9000);
} catch (InterruptedException ex) {
ex.printStackTrace();
}
System.out.println("ReleaseObjectLock");
}
} public static void main(String[] args) {
Thread thread = new Thread(new JoinTester01("Three"));
Thread getLockThread = new Thread(new JoinTester02(thread)); getLockThread.start();
thread.start(); try {
thread.join();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
System.out.println("Main finished!");
} }
输出如下:
getObjectLock
Three begins: Wed Aug 28 10:42:00 CST 2013
Three has finished: Wed Aug 28 10:42:04 CST 2013
ReleaseObjectLock
Main finished!
getLockThread通过 synchronized (thread) ,获取线程对象t的锁,并Sleep(9000)后释放,这就意味着,即使main方法t.join(1000)等待一秒钟,它必须等待ThreadTest 线程释放t锁后才能进入wait方法中。
本文完
参考:
http://uule.iteye.com/blog/1101994
Java 7 Concurency Cookbook
最新文章
- Ajax关于readyState(状态值)和status(状态码)的研究
- JS 节流
- python_Day_02[数组、列表、元组之篇]
- WPF TreeView递归遍历相关方法
- wget下载网站整个目录
- HDU 5266 pog loves szh III (线段树+在线LCA转RMQ)
- 迪杰斯特拉(Dijkstra)算法
- pthread_setschedprio()函数详解!!!
- Matlab的parfor并行编程
- P、NP、NP完全问题
- js操作中要去注意的一些问题
- ATL右键文件菜单
- [nodemon] clean exit - waiting for changes before restart
- OC获取ip地址
- gym102007 E
- VC.判断双字节字符集前导字节集(IsDBCSLeadByte)
- 迈科DPI和运营商合作比较多
- [转]NSIS:常量大全
- 用bind方法保持this上下文
- c++ 编译时检测结构体大小的的宏定义写法