面试题答案
一键面试线程生命周期常见状态
- 新建(New):当一个
Thread
类或其子类的对象被创建时,线程就进入了新建状态。例如:Thread thread = new Thread();
此时线程还没有开始运行,仅仅是一个对象而已。 - 就绪(Runnable):调用
start()
方法后,线程进入就绪状态。在这个状态下,线程等待被线程调度器选中,获取CPU时间片以开始执行。例如:thread.start();
此时线程已做好运行准备,但不一定立即执行。 - 运行(Running):当线程调度器选中就绪状态的线程并分配CPU时间片给它时,线程进入运行状态,开始执行
run()
方法中的代码。 - 阻塞(Blocked):
- 等待阻塞:当线程执行
wait()
方法后,线程会进入等待阻塞状态,释放持有的锁,并等待其他线程调用notify()
或notifyAll()
方法来唤醒它。例如:在一个同步块中,synchronized (obj) { obj.wait(); }
- 同步阻塞:当线程试图获取一个对象的锁,而该锁被其他线程持有时,线程进入同步阻塞状态,直到获取到锁才会进入就绪状态。例如:
synchronized (obj) { // 其他线程持有obj的锁,当前线程阻塞 }
- 其他阻塞:当线程执行
Thread.sleep(long millis)
、join()
等方法时,线程进入其他阻塞状态。sleep
方法会使线程暂停指定的时间,join
方法会使当前线程等待调用join
方法的线程执行完毕。例如:thread.join();
- 等待阻塞:当线程执行
- 死亡(Dead):线程执行完
run()
方法中的代码,或者因异常提前终止,线程进入死亡状态。例如:run()
方法执行结束;或者在run()
方法中抛出未捕获的异常。
状态转换情况
- 新建 -> 就绪:调用
start()
方法。 - 就绪 -> 运行:线程调度器选中该线程并分配CPU时间片。
- 运行 -> 阻塞:
- 调用
wait()
方法进入等待阻塞。 - 尝试获取锁失败进入同步阻塞。
- 调用
sleep(long millis)
、join()
等方法进入其他阻塞。
- 调用
- 阻塞 -> 就绪:
- 等待阻塞时,其他线程调用
notify()
或notifyAll()
方法唤醒等待的线程。 - 同步阻塞时,持有锁的线程释放锁。
- 其他阻塞中,
sleep
时间到或者join
的线程执行完毕。
- 等待阻塞时,其他线程调用
- 运行 -> 死亡:
run()
方法执行完毕或因异常提前终止。