《Java程序员面试秘笈》—— 1.7 等待线程的终止

简介: 在一些情形下,我们必须等待线程的终止。例如,我们的程序在执行其他的任务时,必须先初始化一些必须的资源。可以使用线程来完成这些初始化任务,等待线程终止,再执行程序的其他任务。

本节书摘来异步社区《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()方法跟第一种相似,只是需要接受毫秒和纳秒两个参数。

相关文章
|
11天前
|
安全 架构师 Java
Java大厂面试高频:Collection 和 Collections 到底咋回答?
Java中的`Collection`和`Collections`是两个容易混淆的概念。`Collection`是集合框架的根接口,定义了集合的基本操作方法,如添加、删除等;而`Collections`是一个工具类,提供了操作集合的静态方法,如排序、查找、同步化等。简单来说,`Collection`关注数据结构,`Collections`则提供功能增强。通过小王的面试经历,我们可以更好地理解这两者的区别及其在实际开发中的应用。希望这篇文章能帮助你掌握这个经典面试题。
30 4
|
3天前
|
监控 Kubernetes Java
阿里面试:5000qps访问一个500ms的接口,如何设计线程池的核心线程数、最大线程数? 需要多少台机器?
本文由40岁老架构师尼恩撰写,针对一线互联网企业的高频面试题“如何确定系统的最佳线程数”进行系统化梳理。文章详细介绍了线程池设计的三个核心步骤:理论预估、压测验证和监控调整,并结合实际案例(5000qps、500ms响应时间、4核8G机器)给出具体参数设置建议。此外,还提供了《尼恩Java面试宝典PDF》等资源,帮助读者提升技术能力,顺利通过大厂面试。关注【技术自由圈】公众号,回复“领电子书”获取更多学习资料。
|
7天前
|
安全 Java 程序员
面试直击:并发编程三要素+线程安全全攻略!
并发编程三要素为原子性、可见性和有序性,确保多线程操作的一致性和安全性。Java 中通过 `synchronized`、`Lock`、`volatile`、原子类和线程安全集合等机制保障线程安全。掌握这些概念和工具,能有效解决并发问题,编写高效稳定的多线程程序。
48 11
|
6天前
|
Java Linux 调度
硬核揭秘:线程与进程的底层原理,面试高分必备!
嘿,大家好!我是小米,29岁的技术爱好者。今天来聊聊线程和进程的区别。进程是操作系统中运行的程序实例,有独立内存空间;线程是进程内的最小执行单元,共享内存。创建进程开销大但更安全,线程轻量高效但易引发数据竞争。面试时可强调:进程是资源分配单位,线程是CPU调度单位。根据不同场景选择合适的并发模型,如高并发用线程池。希望这篇文章能帮你更好地理解并回答面试中的相关问题,祝你早日拿下心仪的offer!
25 6
|
11天前
|
监控 Dubbo Java
Java Dubbo 面试题
Java Dubbo相关基础面试题
|
11天前
|
SQL Java 数据库连接
Java MyBatis 面试题
Java MyBatis相关基础面试题
|
11天前
|
存储 监控 算法
Java JVM 面试题
Java JVM(虚拟机)相关基础面试题
|
11天前
|
SQL 监控 druid
Java Druid 面试题
Java Druid 连接池相关基础面试题
|
11天前
|
缓存 安全 算法
Java 多线程 面试题
Java 多线程 相关基础面试题
|
27天前
|
并行计算 算法 安全
面试必问的多线程优化技巧与实战
多线程编程是现代软件开发中不可或缺的一部分,特别是在处理高并发场景和优化程序性能时。作为Java开发者,掌握多线程优化技巧不仅能够提升程序的执行效率,还能在面试中脱颖而出。本文将从多线程基础、线程与进程的区别、多线程的优势出发,深入探讨如何避免死锁与竞态条件、线程间的通信机制、线程池的使用优势、线程优化算法与数据结构的选择,以及硬件加速技术。通过多个Java示例,我们将揭示这些技术的底层原理与实现方法。
81 3

热门文章

最新文章