Appearance
18.1 线程概念
线程的概念
线程(Thread)是程序执行的最小单位,是进程中的一个独立执行路径。一个进程可以包含多个线程,这些线程共享进程的资源,但拥有各自的执行栈和程序计数器。
线程 vs 进程
| 特性 | 进程 | 线程 |
|---|---|---|
| 定义 | 程序的一次执行过程 | 进程中的一个执行单元 |
| 资源分配 | 系统分配资源的基本单位 | 不拥有系统资源,共享进程资源 |
| 独立性 | 进程之间相互独立 | 线程之间共享进程资源 |
| 通信 | 进程间通信复杂(如管道、消息队列) | 线程间通信简单(如共享变量) |
| 切换开销 | 较大 | 较小 |
| 数量 | 系统中进程数量相对较少 | 一个进程中可以有多个线程 |
线程的状态
Java 中的线程有以下几种状态:
- 新建(New):线程对象已创建,但尚未启动
- 运行(Runnable):线程正在执行,或等待 CPU 时间片
- 阻塞(Blocked):线程等待获取锁
- 等待(Waiting):线程等待其他线程的通知
- 超时等待(Timed Waiting):线程等待指定时间后自动唤醒
- 终止(Terminated):线程执行完毕或异常终止
线程的生命周期
线程的生命周期包括以下阶段:
- 创建:通过
new Thread()创建线程对象 - 启动:调用
start()方法启动线程 - 运行:线程执行
run()方法中的代码 - 阻塞/等待:线程因某些原因暂时停止执行
- 终止:线程执行完毕或异常终止
线程的优势
提高程序响应速度:多线程可以同时处理多个任务,提高程序的响应速度
充分利用 CPU 资源:多线程可以充分利用 CPU 的多核资源
简化程序结构:将复杂的任务分解为多个线程,使程序结构更清晰
提高系统吞吐量:多线程可以同时处理多个请求,提高系统的吞吐量
线程的应用场景
GUI 应用:后台处理任务,保持界面响应
服务器应用:同时处理多个客户端请求
批量处理:并行处理大量数据
实时应用:如游戏、实时监控等
示例:多线程的简单应用
java
public class ThreadExample {
public static void main(String[] args) {
// 创建线程
Thread thread1 = new Thread(new MyRunnable(), "线程1");
Thread thread2 = new Thread(new MyRunnable(), "线程2");
// 启动线程
thread1.start();
thread2.start();
// 主线程继续执行
for (int i = 0; i < 5; i++) {
System.out.println(Thread.currentThread().getName() + " 执行: " + i);
try {
Thread.sleep(500);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
class MyRunnable implements Runnable {
@Override
public void run() {
for (int i = 0; i < 5; i++) {
System.out.println(Thread.currentThread().getName() + " 执行: " + i);
try {
Thread.sleep(500);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}线程的创建方式
Java 中创建线程有两种主要方式:
- 继承 Thread 类:
java
public class MyThread extends Thread {
@Override
public void run() {
// 线程执行的代码
}
}
// 创建并启动线程
MyThread thread = new MyThread();
thread.start();- 实现 Runnable 接口:
java
public class MyRunnable implements Runnable {
@Override
public void run() {
// 线程执行的代码
}
}
// 创建并启动线程
Runnable runnable = new MyRunnable();
Thread thread = new Thread(runnable);
thread.start();- 使用 Lambda 表达式(Java 8+):
java
// 使用 Lambda 表达式创建线程
Thread thread = new Thread(() -> {
// 线程执行的代码
});
thread.start();线程的基本操作
- 启动线程:
start()方法 - 暂停线程:
sleep(long millis)方法 - 等待线程:
join()方法 - 中断线程:
interrupt()方法 - 获取线程状态:
getState()方法 - 获取线程名称:
getName()方法 - 设置线程名称:
setName(String name)方法 - 获取当前线程:
Thread.currentThread()方法
示例:线程的基本操作
java
public class ThreadOperationsExample {
public static void main(String[] args) {
Thread thread = new Thread(() -> {
System.out.println("线程开始执行");
try {
// 暂停 2 秒
Thread.sleep(2000);
} catch (InterruptedException e) {
System.out.println("线程被中断");
}
System.out.println("线程执行完毕");
}, "工作线程");
// 启动线程
thread.start();
// 获取线程状态
System.out.println("线程状态: " + thread.getState());
// 等待线程执行完毕
try {
thread.join();
} catch (InterruptedException e) {
e.printStackTrace();
}
// 获取线程状态
System.out.println("线程状态: " + thread.getState());
}
}线程安全
什么是线程安全
线程安全是指多个线程同时访问共享资源时,不会导致数据不一致或其他意外结果的情况。
线程安全问题的原因
- 共享资源:多个线程同时访问同一个资源
- 非原子操作:操作不是原子的,可能被其他线程打断
- 可见性问题:一个线程对共享变量的修改,其他线程可能看不到
- 重排序问题:编译器或 CPU 可能对指令进行重排序
线程安全的解决方案
- 同步代码块:使用
synchronized关键字 - 同步方法:使用
synchronized修饰方法 - 锁:使用
Lock接口及其实现类 - 线程安全的集合:如
ConcurrentHashMap - 原子类:如
AtomicInteger - 线程本地存储:使用
ThreadLocal
示例:线程安全问题
java
public class ThreadSafetyExample {
private static int count = 0;
public static void main(String[] args) {
// 创建 10 个线程,每个线程增加 count 1000 次
for (int i = 0; i < 10; i++) {
new Thread(() -> {
for (int j = 0; j < 1000; j++) {
count++;
}
}).start();
}
// 等待所有线程执行完毕
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
// 打印结果
System.out.println("最终 count 值: " + count);
// 预期结果应该是 10000,但实际结果可能小于 10000
}
}示例:线程安全解决方案
java
public class ThreadSafetySolution {
private static int count = 0;
private static final Object lock = new Object();
public static void main(String[] args) {
// 创建 10 个线程,每个线程增加 count 1000 次
for (int i = 0; i < 10; i++) {
new Thread(() -> {
for (int j = 0; j < 1000; j++) {
synchronized (lock) {
count++;
}
}
}).start();
}
// 等待所有线程执行完毕
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
// 打印结果
System.out.println("最终 count 值: " + count);
// 结果应该是 10000
}
}总结
线程是 Java 中实现并发编程的重要机制:
线程的概念:线程是程序执行的最小单位,是进程中的一个独立执行路径
线程 vs 进程:线程共享进程资源,切换开销小,通信简单
线程的状态:新建、运行、阻塞、等待、超时等待、终止
线程的生命周期:创建、启动、运行、阻塞/等待、终止
线程的优势:提高程序响应速度、充分利用 CPU 资源、简化程序结构、提高系统吞吐量
线程的创建方式:继承 Thread 类、实现 Runnable 接口、使用 Lambda 表达式
线程的基本操作:启动、暂停、等待、中断等
线程安全:多个线程同时访问共享资源时的安全问题及解决方案
通过合理使用线程,可以充分利用系统资源,提高程序的性能和响应速度。
