线程生命周期
线程的五种状态:新建(New)、就绪(Ready)、运行(Running)、阻塞(Blocked)、死亡(Dead)
新建状态
当创建一个Thread对象时,线程进入新建状态。此时线程还没有开始执行,但是它的相关资源已经被分配
1 | public static void main(String[] args) { |
就绪、运行状态
调用线程的start()方法会使线程进入就绪状态。处于就绪状态的线程已经具备了执行条件,等待系统的调度器分配CPU时间片。
当就绪状态的线程获得了CPU时间片,将开始执行run()方法中的代码,线程进入运行状态
1 | public static void main(String[] args) { |
阻塞状态
在抢占式策略的系统中,线程开始执行后不会一直处于运行状态,因为CPU时间片同时也要分配给其他线程,所以当运行中的线程时间片用完时,将会进入阻塞状态。在多线程编程中,操作系统的调度器会负责分配CPU时间片给各个线程。每个线程在运行一段时间后,操作系统会将CPU时间片切换给其他就绪状态的线程,以实现多个线程之间的并发执行。因此,即使线程处于运行状态,它也会被操作系统调度器抢占,从而让其他线程有机会执行。
此外,在发生如下情况时,线程将会进入阻塞状态
- 调用阻塞式IO操作:当线程执行阻塞式的输入/输出操作时,比如读取文件、网络通信等,线程会被阻塞,直到IO操作完成或超时。
- 调用
sleep()方法:线程可以通过调用Thread.sleep(milliseconds)方法来主动暂停执行一段时间。在这段时间内,线程会进入阻塞状态。 - 等待获取锁:线程在并发编程中可能需要获取共享资源的锁。如果某个线程在执行过程中发现锁已经被其他线程占用,那么该线程会被阻塞,直到锁被释放。
- 等待条件的满足:线程在某些情况下需要等待特定的条件满足才能继续执行。通过调用
wait()方法进入等待状态,并在其他线程中满足条件后通过notify()或notifyAll()方法唤醒。 - 加入其他线程:通过调用
Thread.join()方法,一个线程可以等待另一个线程执行完毕后再继续执行。在等待期间,线程会进入阻塞状态。
当正在执行的线程被阻塞后,其他线程就可以获得执行的机会,阻塞解除后,线程将重新进入就绪状态
死亡状态
以下三种情况,会导致线程死亡,死亡后的线程不可以再次通过调用start()启动,通过isAlive()方法,可以判断线程是否为死亡状态
run()或call()方法执行完成,线程正常结束- 线程抛出一个未捕获的Exception或Error
- 调用该线程的
stop()方法结束线程