本节书摘来异步社区《Java 7并发编程实战手册》一书中的第1章,第1.7节,作者:【西】Javier Fernández González,更多章节内容可以访问云栖社区“异步社区”公众号查看。
在一些情形下,我们必须等待线程的终止。例如,我们的程序在执行其他的任务时,必须先初始化一些必须的资源。可以使用线程来完成这些初始化任务,等待线程终止,再执行程序的其他任务。
为了达到这个目的,我们使用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()方法跟第一种相似,只是需要接受毫秒和纳秒两个参数。