Join java_简谈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()主线程。例如:

package com.bijian.test;

import java.util.Date;

import java.util.concurrent.TimeUnit;

public class JoinTester01 implements Runnable {

private String name;

public JoinTester01(String name) {

this.name = name;

}

public void run() {

System.out.printf("%s begins: %sn", name, new Date());

try {

TimeUnit.SECONDS.sleep(4);

} catch (InterruptedException e) {

e.printStackTrace();

}

System.out.printf("%s has finished: %sn", 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) {

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

但有了join()方法,输出如下:

One begins: Sun Jan 20 17:53:38 CST 2019

Two begins: Sun Jan 20 17:53:38 CST 2019

Two has finished: Sun Jan 20 17:53:42 CST 2019

One has finished: Sun Jan 20 17:53:42 CST 2019

Main thread is finished

可以看出主线程main比其它两个线程先结束。

最后来深入了解一下join(),请看其源码:

/**

* Waits at most {@code millis} milliseconds for this thread to

* die. A timeout of {@code 0} means to wait forever.

*

*

This implementation uses a loop of {@code this.wait} calls

* conditioned on {@code this.isAlive}. As a thread terminates the

* {@code this.notifyAll} method is invoked. It is recommended that

* applications not use {@code wait}, {@code notify}, or

* {@code notifyAll} on {@code Thread} instances.

*

* @param millis

* the time to wait in milliseconds

*

* @throws IllegalArgumentException

* if the value of {@code millis} is negative

*

* @throws InterruptedException

* if any thread has interrupted the current thread. The

* interrupted status of the current thread is

* cleared when this exception is thrown.

* 此处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对象的锁。

package com.bijian.test;

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) {

e.printStackTrace();

}

System.out.println("Main finished!");

}

}

输出如下:

getObjectLock

Three begins: Sun Jan 20 18:05:31 CST 2019

Three has finished: Sun Jan 20 18:05:35 CST 2019

ReleaseObjectLock

Main finished!

getLockThread通过 synchronized(thread),获取线程对象t的锁,并Sleep(9000)后释放,这就意味着,即使main方法t.join(1000)等待一秒钟,它必须等待ThreadTest 线程释放t锁后才能进入wait方法中。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值