系列文章导航

  1. Java 内存管理面试指南一
  2. Java 基础面试指南一
  3. Java 基础面试指南二
  4. Java 基础面试指南三
  5. Java 基础面试指南四
  6. Java 线程面试指南一
  7. Java 线程面试指南二
  8. Redis 面试指南一
  9. Kafka 面试指南一
  10. Spring 面试指南一
  11. SpringBoot 面试指南一
  12. 微服务面试指南一

什么是多线程?

多线程(Multithreading)是指同时执行多个线程的过程。Java 支持单线程以及多线程操作。单线程程序具有一个入口点(main() 方法)和一个出口点;而多线程程序具有一个初始入口点(main() 方法),其后是许多入口点和出口点,它们与 main() 方法同时运行。术语并发(Concurrency)是指同时执行多个任务。多处理和多线程都用于执行多任务。

它的主要优点是:

  • 线程共享相同的地址空间。
  • 线程是轻量级的。
  • 线程之间的切换成本低。

用户线程和守护线程之间有什么区别?

当我们在 Java 程序中创建线程时,它被称为用户线程(User Thread)。守护线程(Daemon Thread)在后台运行,并且不会阻止 JVM 终止。当没有用户线程在运行时,JVM 会关闭程序并退出。从守护线程创建的子线程也是守护线程。

什么是多线程中的上下文切换?

上下文切换(Context Switch)是存储和恢复 CPU 状态的过程,以便可以在以后的某个时间点从同一点恢复线程执行。上下文切换是多任务操作系统的基本功能,并且支持多线程环境。

多线程编程的好处是什么?

在多线程编程中,多个线程同时执行可以提高性能。因为在某些线程正在等待获取某些资源的情况下,CPU 不会处于空闲状态。多个线程共享堆内存,因此最好创建多个线程来执行某些任务,而不要创建多个进程。例如,Servlet 的性能比 CGI 更好,因为 Servlet 支持多线程,但 CGI 不支持。

线程的生命周期有哪些不同状态?

当我们在 Java 程序中创建线程时,其状态为“新建”(New)。然后,我们启动将其状态更改为“可运行”(Runnable)的线程。线程调度程序负责将 CPU 分配给可运行线程池中的线程,并将其状态更改为“运行”(Running)。其他线程状态为“等待”(Waiting)、“阻塞”(Blocked)和“终止”(Dead/Terminated)。

Process 和 Thread 有什么区别?

进程(Process)是一个自包含的执行环境,可以将其视为程序或应用程序;而线程(Thread)是进程中执行的单个任务。Java 运行时环境作为单个进程运行,其中包含不同的类和程序作为进程。线程可以称为轻量级进程。线程需要较少的资源来创建并存在于进程中,线程共享进程资源。

抢占式调度和时间分片有什么区别?

  • 抢占式调度:最高优先级的任务会一直执行,直到进入等待状态、终止状态或存在更高优先级的任务为止。
  • 时间分片:任务将执行预定义的时间片,然后重新进入就绪任务池。然后,调度程序根据优先级和其他因素确定下一步应执行的任务。

是否可以启动一个线程两次?

不,不可能两次启动一个线程。如果这样做,它将引发异常(IllegalThreadStateException)。

我们可以调用 run() 方法而不是 start() 吗?

是的,但是它将不能用作线程,而可以用作普通对象,因此在线程之间不会进行上下文切换。直接调用 run() 方法只是在当前线程中执行普通方法调用。

我们如何在特定时间内暂停执行线程?

我们可以使用 Thread 类的 sleep() 方法将 Thread 的执行暂停一定时间。请注意,这不会在特定时间内停止线程的处理,一旦线程从睡眠中醒来,其状态将更改为可运行,并根据线程调度执行该线程。

什么是线程调度程序和时间切片?

  • 线程调度程序:是一种操作系统服务,它将 CPU 时间分配给可用的可运行线程。创建并启动线程后,其执行取决于 Thread Scheduler 的实现。
  • 时间分片:是将可用 CPU 时间划分为可用可运行线程的过程。可以根据线程优先级为线程分配 CPU 时间,或者等待更长时间的线程将在获得 CPU 时间时获得更高的优先级。线程调度不能由 Java 控制,因此始终最好从应用程序本身控制线程调度。

线程如何相互通信?

当线程共享资源时,线程之间的通信对于协调其工作很重要。Object 类的 wait()notify()notifyAll() 方法允许线程就资源的锁定状态进行通信。

我们如何在 Java 中实现线程安全?

有几种方法可以在 Java 中实现线程安全:

  • 同步(synchronization
  • 原子并发类(atomic concurrent classes)
  • 实现并发 Lock 接口(Lock interface)
  • 使用 volatile 关键字
  • 使用不可变类(Immutable Classes)
  • 使用线程安全类(Thread-safe Classes)

如何在 Java 中创建守护程序线程?

ThreadsetDaemon(true) 可用于在 Java 中创建守护程序线程。我们需要在调用 start() 方法之前调用此方法,否则它将引发 IllegalThreadStateException

什么是 ThreadLocal?

Java ThreadLocal 用于创建线程局部变量。我们知道对象的所有线程都共享它的变量,因此,如果变量不是线程安全的,则可以使用同步,但是如果要避免同步,则可以使用 ThreadLocal 变量。

每个线程都有自己的 ThreadLocal 变量,他们可以使用它的 get()set() 方法获取默认值或将其本地值更改为当前线程。ThreadLocal 实例通常是希望将状态与线程关联的类中的私有静态字段。

什么是 Java Thread Dump,我们如何获取程序的 Java Thread Dump?

Thread Dump 是 JVM 中所有活动线程的列表,Thread Dump 对于分析应用程序中的瓶颈和分析死锁情况非常有帮助。我们可以使用多种方法来 Dump Thread:

  • 使用 Profiler
  • 使用 kill -3 命令
  • 使用 jstack 工具等

我更喜欢使用 jstack 工具来进行 Dump Thread,因为它易于使用并且随 JDK 安装一起提供。由于它是基于终端的工具,因此我们可以创建脚本以定期 Dump Thread,以供日后分析。

什么是线程池?我们如何在 Java 中创建线程池?

线程池管理工作线程池;它包含一个使任务等待执行的队列。线程池管理可运行线程的集合,工作线程从队列中执行可运行线程。

java.util.concurrent.Executors 提供 java.util.concurrent.Executor 接口的实现,以在 Java 中创建线程池。线程池示例程序显示了如何在 Java 中创建和使用线程池。或阅读 ScheduledThreadPoolExecutor 示例以了解如何在特定延迟后安排任务。

什么是同步?

同步(Synchronization)是控制多个线程对任何共享资源的访问的能力。它用于:

  1. 为了防止线程干扰。
  2. 以防止一致性问题。

同步块的目的是什么?

  • 同步块用于锁定任何共享资源的对象。
  • 同步块的范围小于该方法。

什么是静态同步?

如果将任何静态方法设置为已同步,则锁定将锁定在类上而不是对象上。


说明:本文内容基于 Java 多线程基础概念整理,适用于 Java 5 及以上版本(涉及 java.util.concurrent 包特性)。部分术语(如线程状态)在不同 Java 版本中可能存在细微差异,实际开发中请以官方文档为准。