【JavaEE初阶】 多线程编程核心:解锁线程创建、方法与状态的创新实践密码

2025-11-17 17:12:53
文章摘要
本文介绍Java线程核心知识:线程是进程内的执行流,共享进程资源,比进程更轻量,是系统调度最小单位。Java中可通过继承Thread、实现Runnable等方式创建线程,核心方法有start、join、interrupt等。线程有6种状态,多线程实现并发执行,能提升CPU利用率,需注意调度随机性与线程安全。


一:初识线程(Thread)

1.1:线程的概念

一个线程就是一条 “执行流”。每个线程各自按顺序执行自己的代码,多个线程之间则 “并发” 执行多份代码。线程(Thread) 是操作系统能够进行运算调度的最小单位。它被包含在进程之中,是进程中的实际运作单位。


举一个例子:厨房做菜

想象一个繁忙的厨房正在准备顾客丰盛的晚餐,这个厨房就是一个 “进程”。


进程:一个正在执行的程序实例。它拥有独立的资源,如内存空间、文件句柄等。就像这个厨房,它拥有自己的空间、厨具、食材等资源。


线程:进程内部的一个独立执行流。一个进程可以包含多个线程,它们共享进程的资源。就像厨房里的厨师,每位厨师都是一个独立的“线程”。


这里就可以分为:



1.2:为什么需要线程?

首先,“并发编程”已成为“刚需”。单核CPU的发展遭遇瓶颈,要提升算力就需依赖多核CPU,而并发编程能更充分地利用多核CPU资源。

部分任务场景存在“等待IO”的情况,为了在等待IO的时间里处理其他工作,也需要用到并发编程。CPU可以切换到另一个线程去执行,避免了CPU时间的浪费。**就像一位厨师在等待水烧开时,可以先去切菜,而不是空等。


其次,尽管多进程也能实现并发编程,但线程比进程更轻量:

- 创建线程比创建进程更快;

- 销毁线程比销毁进程更快;

- 调度线程比调度进程更高效。


但是,即便线程已比进程轻量,人们仍不满足,进而发展出了“线程池”(ThreadPool)和“协程”(Coroutine)。


1.3:进程和线程的区别是什么?

- 进程包含线程,每个进程至少存在一个线程,即主线程。

- 进程之间不共享内存空间,而同一进程内的线程共享该进程的内存空间。

- 进程是系统分配资源的最小单位,线程是系统调度的最小单位。

- 一个进程崩溃通常不会影响其他进程,但一个线程崩溃可能导致整个进程(及其中所有线程)一同崩溃。


1.4:Java 的线程和操作系统线程的关系

线程是操作系统层面的概念,其机制由操作系统内核实现,并向用户层提供API供调用(例如Linux的pthread库)。

Java标准库中的Thread类,可视为对操作系统提供的线程API进行了进一步的抽象与封装。




二:多线程程序的编写

2.1:继承 Thread 类



可以看到hello thread和hello main都打印出来了,但不是交替出现的。这里就体现了操作系统调度线程是随机的。每个线程都是独立的工作流,多个线程之间是并发执行的。


当我们将主线程中的`thread.start()`换成`thread.run()`,由于是死循环,只会看到打印hello thread:


> 在这里我们可以利用Java中的jconsole命令观察线程


右键点击以管理员身份运行,选择正在运行的线程,点击连接即可:


其中main是主线程,Thread-0是通过MyThread类创建的线程,其他线程是JVM自带的,负责线程相关的后台操作。

点击main可以看到详细信息:



这是使用thread.start()的情况,当使用thread.run()时,就没有Thread-0线程了:


2.2:实现 Runnable 接口




> 注意:

> runnable 没有 start 方法,要想启动线程,需要搭配 Thread,不能直接调用 runnable.start();


2.3:匿名内部类创建 Thread 子类对象



2.4:匿名内部类创建 Runnable 子类对象



2.5:lambda 表达式创建 Runnable 子类对象



---


三:多线程下的运行速度对比

使用 `System.nanoTime()` 可记录系统的纳秒级时间戳,通过对比串行和并发执行的耗时,观察多线程的速度优势:

- 串行(serial):单线程依次完成一系列运算

- 并行(concurrency):通过两个线程同时执行相同运算


示例代码



运行结果

> 注意:多线程并不一定就能提高速度,count 不同,实际的运行效果也会不同。


---


四:Thread类及常见方法

在 Java 中,`Thread` 类是 JVM 用来管理线程的核心类。**每个线程在 JVM 中都对应一个唯一的 `Thread` 对象**,通过这个对象可以对线程的状态、行为进行控制和管理。


4.1:Thread常见的构造方法


说明:

- 最常用的构造方法是 `Thread(Runnable target)` 和 `Thread(Runnable target, String name)`,通过传入 `Runnable` 对象分离任务逻辑,更符合面向对象设计。

- 线程名称可通过 `setName()` 后续修改,但建议在构造时指定,便于早期调试。

- 线程组(`ThreadGroup`)主要用于线程的批量管理,日常开发中使用较少,除非需要对一组线程进行统一操作(如销毁所有子线程)。


修改线程名称示例


通过jconsole可以看到修改后的线程名字:



> 注意:为什么这个线程中没有看到main?

> - 因为start执行完毕后,main方法就运行结束了。

> - main方法结束,对应的main线程就会销毁。

> - 线程对应的"入口方法"执行完毕,该线程就会自动销毁。


## 4.2:Thread几个常见的属性


后台线程与前台线程说明

- 前台线程:线程没有运行完,进程就不会结束(线程可以阻止进程结束)。

- 后台线程:线程没有运行完,进程也可以结束(线程不能阻止进程结束)。


应用场景

- 任务重要且必须完成时,设置为前台线程。

- 任务无关紧要或周期性无期限执行时,设置为后台线程。


设置后台线程示例

通过`.setDaemon()`设置线程为后台线程,该操作必须在**start**之前执行。


线程存活状态(isAlive())示例


![isAlive()执行结果]



> 线程正在执行时,isAlive()返回true;线程执行完毕后,isAlive()返回false。


4.3:启动一个线程 - start()

示例代码


![start()执行结果]


说明

- start()调用后,main线程和t线程是**并发执行**的关系。

- 操作系统对线程的调度是随机的,所以也可能出现先打印`hello thread`的情况。

- 重点:一个**线程对象**只能调用start**一次**,多次调用会报错。


多次start()报错示例

![多次start()报错]


4.4:中断一个线程

Thread 内部包含了一个 boolean 类型的变量作为线程是否被中断的标记:

![中断标记示意图]


基本中断示例

使用Thread的静态方法`currentThread()`获取当前线程引用:



包含sleep()的中断处理

当线程处于sleep状态时,调用interrupt()会提前唤醒sleep并触发InterruptException,同时重置中断标记为false,此时需要手动处理线程终止:





中断逻辑说明

- 线程未阻塞时,interrupt()会设置中断标记为true,通过循环条件结束线程。

- 线程阻塞时(如sleep),interrupt()会触发异常并重置中断标记,需在catch中手动决定是否结束线程。

- 本质上,interrupt()是向线程发送“终止建议”,线程自行决定是否终止。


4.5:线程等待-join()

线程等待是指一个线程等待另一个线程执行完毕后再继续执行。


示例1:main线程等待t线程结束




示例2:t线程等待main线程结束



join()方法重载版本




join()核心逻辑

- 调用join()的线程是“等待方”。

- join()的调用对象是“被等待方”。


---


五:线程的状态

5.1:线程的状态枚举(Thread.State)

在 Java 中,线程(`Thread`)的生命周期包含 6 种状态,定义在 `Thread.State` 枚举类中:


可通过 `Thread.getState()` 方法获取线程当前状态。


状态示例代码




状态监控示例

通过jconsole观察线程状态:

- main线程状态(执行join()时):


- t线程状态(执行sleep()时):



状态转换关键点

- `NEW` → `RUNNABLE`:调用 `start()` 方法后进入可运行状态。

- `RUNNABLE` → `BLOCKED`:竞争同步锁失败时进入阻塞状态,获取锁后回到 `RUNNABLE`。

- `RUNNABLE` → `WAITING`/`TIMED_WAITING`:调用 `wait()`、`join()` 等方法时进入等待状态,被唤醒或超时后回到 `RUNNABLE`。

- 所有状态 → `TERMINATED`:线程执行完成或异常终止后进入终止状态,无法再切换到其他状态。


---


声明:该内容由作者自行发布,观点内容仅供参考,不代表平台立场;如有侵权,请联系平台删除。