一个线程可以在其它线程之上调用 join( )方法,其效果是等待一段时间直到第二个线程
结束才继续执行。如果某个线程在另一个线程 t 上调用 t.join(),此线程将被挂起,直
到目标线程t 结束才恢复(即 t.isAlive()返回为假)。
你也可以在调用join( )时带上一个超时参数(单位可以是毫秒或者毫秒加纳秒),这样
如果目标线程在这段时间到期时还没有结束的话,join( )方法总能返回。
对 join( )方法的调用可以被中断,做法是在调用线程上调用 interrupt()方法,这时
需要用到try-catch 子句。
下面这个例子演示了所有这些操作:
//: c13:Joining.java
// Understanding join().
import com.bruceeckel.simpletest.*;
class Sleeper extends Thread {
private int duration;
public Sleeper(String name, int sleepTime) {
super(name);
duration = sleepTime;
start();
}
public void run() {
try{
sleep(duration);
} catch(InterruptedException e) {
System.out.println(getName() + " was
interrupted. " +
"isInterrupted(): " + isInterrupted());
return;
}
System.out.println(getName() + " has awakened");
}
}
class Joiner extends Thread {
private Sleeper sleeper;
public Joiner(String name, Sleeper sleeper) {
super(name);
this.sleeper= sleeper;
start();
}
public void run() {
try{
sleeper.join();
} catch(InterruptedException e) {
throw newRuntimeException(e);
}
System.out.println(getName() + " join
completed");
}
}
public class Joining {
private static Test monitor = new Test();
public static void main(String[] args) {
Sleeper
sleepy = newSleeper("Sleepy", 1500),
grumpy = newSleeper("Grumpy", 1500);
Joiner
dopey = newJoiner("Dopey", sleepy),
doc = newJoiner("Doc", grumpy);
grumpy.interrupt();
monitor.expect(new String[] {
"Grumpy was interrupted.isInterrupted():
false",
"Doc join completed",
"Sleepy has awakened",
"Dopey join completed"
},Test.AT_LEAST + Test.WAIT);
}
} ///:~
Sleeper 是一个 Thread 类型,它要休眠一段时间,这段时间是通过构造器传进来的参
数所指定的。在run( )中,sleep( )方法有可能在指定的时间期满时返回,但也可能
被中断。在catch 子句中,将根据 isInterrupted()的返回值报告这个中断。当另
一个线程在该线程上调用 interrupt()时,将给该线程设定一个标志,表明该线程已
经被中断。然而,异常被捕获时将清除这个标志,所以在异常被捕获的时候这个标志总
是为假。除异常之外,这个标志还可用于其它情况,比如线程可能会检查其中断状态。
Joiner 线程将通过在 Sleeper对象上调用 join()方法来等待Sleeper 醒来。在
main( )里面,每个 Sleeper都有一个 Joiner,你可以在输出中发现,如果 Sleeper
被中断或者是正常结束,Joiner 将和 Sleeper一同结束。