本节书摘来异步社区《Java 7并发编程实战手册》一书中的第1章,第1.7节,作者:【西】Javier Fernández González,更多章节内容可以访问云栖社区“异步社区”公众号查看。
1.7 等待线程的终止
在一些情形下,我们必须等待线程的终止。例如,我们的程序在执行其他的任务时,必须先初始化一些必须的资源。可以使用线程来完成这些初始化任务,等待线程终止,再执行程序的其他任务。
为了达到这个目的,我们使用Thread类的join()方法。当一个线程对象的join()方法被调用时,调用它的线程将被挂起,直到这个线程对象完成它的任务。
在本节中,我们将通过初始化资源的范例来学习join()方法。
准备工作
本节的范例是在Eclipse IDE里完成的。无论你使用Eclipse还是其他的IDE(比如NetBeans),都可以打开这个IDE并且创建一个新的Java工程。
范例实现
按照接下来的步骤实现本节的范例。
1.创建名为DataSourcesLoader的类,并且实现Runnable接口。
``
public class DataSourcesLoader implements Runnable {``
2.实现run()方法。这个方法先显示一个表明它开始执行的信息,然后休眠4秒钟,再显示另一个信息表明已完成当前执行。
@Override
public void run() {
System.out.printf("Beginning data sources loading: %s\n",new Date());
try {
TimeUnit.SECONDS.sleep(4);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.printf("Data sources loading has finished: %s\n",new Date());
}```
3.创建一个NetworkConnectionsLoader类,用以实现Runnable接口。实现run()方法的方式与DataSourcesLoade的run()方法类似,但是它休眠6秒钟。
4.创建一个包含main()方法的Main类。
public class Main {
public static void main(String[] args) {`
5.创建一个DataSourcesLoader对象,并用它作为传入参数来创建一个线程。
DataSourcesLoader dsLoader = new DataSourcesLoader();
Thread thread1 = new Thread(dsLoader,"DataSourceThread");```
6.创建一个NetworkConnectionsLoader对象,并用它作为传入参数来创建一个线程。
NetworkConnectionsLoader ncLoader = new NetworkConnectionsLoader();
Thread thread2 = new Thread(ncLoader,"NetworkConnectionLoader");`
7.调用start()方法启动这两个线程对象。
thread1.start();
thread2.start();```
8.使用join()方法等待两个线程的终止。join()方法会抛出InterruptedException异常,我们必须捕获并处理这个异常。
try {
thread1.join();
thread2.join();
} catch (InterruptedException e) {
e.printStackTrace();
}`
9.程序运行结束时,打印出信息。
``
System.out.printf("Main: Configuration has been loaded: %sn",new Date());``
10.运行程序并观察运行结果。
工作原理
运行这个程序时,你会看到两个线程对象是如何运行的。DataSourcesLoader线程运行结束,NetworkConnectionsLoader线程也运行结束的时候,主线程对象才会继续运行并且打印出最终的信息。
更多信息
Java提供了另外两种形式的join()方法:
join (long milliseconds)
join (long milliseconds, long nanos)
当一个线程调用其他某个线程的join()方法时,如果使用的是第一种join()方式,那么它不必等到被调用线程运行终止,如果参数指定的毫秒时钟已经到达,它将继续运行。例如,thread1中有这样的代码thread2.join(1000),thread1将挂起运行,直到满足下面两个条件之一:
◆ thread2运行已经完成;
◆ 时钟已经过去1000毫秒。
当两个条件中的任何一条成立时,join()方法将返回。
第二种join()方法跟第一种相似,只是需要接受毫秒和纳秒两个参数。