线程的生命周期及其各个阶段
线程的生命周期包括多个阶段,从创建到终止。每个阶段都有不同的特性和行为。以下是 C# 中线程的主要生命周期阶段及其特点:
1. 未启动(Unstarted)
- 状态:
ThreadState.Unstarted
- 描述: 线程已被创建,但尚未启动。
- 特性:
- 在此阶段,线程对象已经被初始化,但
Start()
方法尚未调用。 - 线程未分配 CPU 资源,也不会执行任何代码。
- 在此阶段,线程对象已经被初始化,但
- 操作:
- 调用
Start()
方法将线程转为 可运行状态。
- 调用
示例代码:
Thread thread = new Thread(SomeMethod);
// 线程处于未启动状态
2. 可运行(Runnable)
- 状态:
ThreadState.Running
(具体运行时)或ThreadState.WaitSleepJoin
(阻塞中) - 描述: 线程已启动,并等待 CPU 分配资源。
- 特性:
- 线程已准备好运行,但可能正在等待调度器分配 CPU 时间片。
- 线程在这个状态中可能执行代码,也可能因为等待资源而暂时阻塞。
- 操作:
- 调用
Start()
方法会将线程置于此状态。 - 线程会在调度器中根据优先级和资源情况安排运行。
- 调用
示例代码:
Thread thread = new Thread(SomeMethod);
thread.Start(); // 线程进入可运行状态
3. 阻塞(Blocked)
- 状态:
ThreadState.WaitSleepJoin
- 描述: 线程被挂起,暂时无法继续运行。
- 特性:
- 常见阻塞场景包括线程调用
Sleep()
、等待锁资源(如lock
)、或执行 I/O 操作。 - 线程需要等待特定条件满足后才能继续运行。
- 常见阻塞场景包括线程调用
- 常见方法:
Thread.Sleep(milliseconds)
:使线程挂起一段时间。- 等待同步资源(如
lock
、Monitor.Wait()
)。
- 操作:
- 阻塞结束后,线程会重新进入可运行状态。
示例代码:
lock (someObject) // 等待锁资源
{
Thread.Sleep(1000); // 睡眠 1 秒,进入阻塞状态
}
4. 等待(Waiting)
- 状态:
ThreadState.WaitSleepJoin
- 描述: 线程等待另一个线程的终止或某个事件发生。
- 特性:
- 调用
Thread.Join()
,使当前线程等待另一个线程完成。 - 或者等待事件通知(如使用
ManualResetEvent
或AutoResetEvent
)。
- 调用
- 操作:
- 等待条件满足后,线程会从此状态恢复为可运行状态。
示例代码:
Thread thread = new Thread(SomeMethod);
thread.Start();
thread.Join(); // 当前线程等待 `thread` 完成
5. 停止(Stopped/Terminated)
- 状态:
ThreadState.Stopped
- 描述: 线程已完成执行,生命周期结束。
- 特性:
- 线程执行的代码完成或被显式终止(
Abort
方法已弃用)。 - 线程进入终止状态后不能再重新启动。
- 线程执行的代码完成或被显式终止(
- 操作:
- 调用
Abort()
(不推荐,已被弃用)。 - 程序代码自然执行结束。
- 调用
示例代码:
Thread thread = new Thread(SomeMethod);
thread.Start();
thread.Join(); // 此时线程已完成并进入停止状态
6. 中止(Aborted)
- 状态:
ThreadState.Aborted
(C# 早期版本) - 描述: 线程被外部强制终止。
- 特性:
- 调用
Thread.Abort()
会触发线程终止,但这种方法已被弃用,因为会导致线程不安全。
- 调用
- 替代方案:
- 使用标志变量结合线程安全机制优雅地结束线程。
线程状态的转化图
+-------------+
| 未启动 |
+-------------+
|
V
+-------------+
| 可运行 |
+-------------+
| |
V V
+-------------+ +------------+
| 阻塞中 | | 停止状态 |
+-------------+ +------------+
总结
线程的生命周期涉及多个状态,包括 未启动、可运行、阻塞、等待、停止 等。理解这些状态及其特点有助于编写高效的多线程程序,避免常见问题如线程死锁、资源竞争等。