线程创建、启动、停止
一、线程创建
是什么?
线程是程序执行的最小单位,线程创建指在Java中生成一个可执行的任务单元。JDK8后主要支持三种方式:
- 继承
Thread
类 - 实现
Runnable
接口 - 实现
Callable
接口(JDK5+,配合Future/FutureTask)
解决什么问题
- 实现并发执行,提高CPU利用率
- 避免主线程阻塞(如耗时I/O操作)
- 充分利用多核处理器资源
核心方法
java
// 方式1:继承Thread
class MyThread extends Thread {
public void run() { /* 任务逻辑 */ }
}
// 方式2:实现Runnable
class MyRunnable implements {
public void run() { /* 任务逻辑 */ }
}
// 方式3:实现Callable(可返回结果)
class MyCallable implements Callable<String> {
public String call() { return "结果"; }
}
应用场景
- 后台任务处理(如日志写入)
- 异步计算(如并行数据处理)
- 实时响应(如GUI事件处理)
Java示例(JDK8+)
java
// Lambda简化Runnable(JDK8+)
Thread lambdaThread = new Thread(() -> {
System.out.println("Lambda线程运行中");
});
// CompletableFuture异步任务(JDK8+)
CompletableFuture.runAsync(() -> {
System.out.println("CompletableFuture线程");
});
重要注意事项
- 优先选择
Runnable
/Callable
(避免Java单继承限制) - 线程创建开销大,高并发场景推荐用线程池
- JDK8的Lambda可简化匿名内部类写法
二、线程启动
是什么?
通过调用 start()
方法使线程进入就绪状态,等待JVM调度执行。
解决什么问题
- 激活线程执行(区别于直接调用
run()
) - 由操作系统管理线程调度
- 实现真正的并发执行
核心方法
java
thread.start(); // 启动线程(非阻塞)
应用场景
- 需要并发执行的任何场景
- 定时任务触发
- 事件驱动编程
Java示例
java
// 正确启动方式
MyThread thread = new MyThread();
thread.start(); // JVM自动调用run()
// 错误方式(不会启动新线程)
thread.run(); // 仅在当前线程执行
重要注意事项
start()
只能调用一次,重复调用抛IllegalThreadStateException
- 启动顺序 ≠ 执行顺序(由线程调度器决定)
- JDK19虚拟线程(预览特性)启动方式相同
三、线程停止
是什么?
安全终止线程执行的过程。Java不推荐直接使用废弃的 stop()
方法。
解决什么问题
- 避免资源未释放(如文件句柄、数据库连接)
- 防止数据不一致(突然终止导致状态异常)
- 实现优雅退出
核心方法
java
// 协作式中断(推荐)
thread.interrupt(); // 设置中断标志
// 标志位停止(需volatile保证可见性)
private volatile boolean stopped = false;
应用场景
- 用户取消长时间操作
- 服务关闭时停止工作线程
- 超时任务终止
Java示例
java
// 方法1:检查中断标志
class SafeThread extends {
public void run() {
while (!Thread.currentThread().isInterrupted()) {
// 执行任务
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
// 捕获中断异常后需重置标志
Thread.currentThread().interrupt();
break;
}
}
}
}
// 方法2:使用标志位
class FlagThread extends {
private volatile boolean stopped = false;
void stopThread() { stopped = true; }
public void run() {
while (!stopped) {
// 执行任务
}
}
}
重要注意事项
- 禁止使用
stop()
/suspend()
/resume()
(已废弃,会导致死锁/数据损坏) - 阻塞方法(如
sleep()
/wait()
)会抛InterruptedException
- 捕获中断异常后必须重置中断标志(调用
interrupt()
) - JDK7+的
try-with-resources
可配合自动关闭资源
区别对比
特性 | Thread 类继承 | Runnable 接口 | Callable 接口 |
---|---|---|---|
返回值 | 无 | 无 | 有(通过Future获取) |
异常处理 | 只能在run()内部处理 | 同左 | 可向外抛出异常 |
单继承限制 | 受限制 | 不受限 | 不受限 |
JDK8+Lambda支持 | 不支持 | 支持 | 支持 |
总结
- 创建:优先选
Runnable
/Callable
,JDK8+可用Lambda简化 - 启动:必须通过
start()
,直接调用run()
不会启动新线程 - 停止:
- 使用协作式中断(
interrupt()
+ 状态检查) - 阻塞方法需捕获
InterruptedException
- 资源释放放在
finally
块中
- 使用协作式中断(
- 最佳实践:java
// JDK5+线程池示例 ExecutorService pool = Executors.newFixedThreadPool(4); pool.submit(() -> { while (!Thread.interrupted()) { // 任务逻辑 } }); pool.shutdown(); // 优雅关闭
- 新特性:
- JDK19虚拟线程(轻量级线程,高并发场景)
CompletableFuture
(JDK8+异步编程)ForkJoinPool
(分治任务处理)