Java多线程 - 线程生命周期

当线程被创建并启动后,它既不是一启动就进入了执行状态,也不是一直处于执行状态,在线程的生命周期中,它要经历新建(New)、就绪(Runnable)、运行(Running)、阻塞(Blocked)和死亡(Dead)5种状态。尤其在线程启动后,它不可能一直“霸占”着CPU独自运行,所以CPU工作需要多条线程之间切换,于是线程状态也会多次在运行、阻塞之间切换。

一、新建和就绪状态

新建状态:

当程序使用new关键字创建一个线程之后,该线程就处于新建状态,此时仅由JVM为其分配内存,并初始化其成员变量的值。此时的线程对象没有表现出任何线程的动态特征,程序也不会执行线程的执行体。

就绪状态:

当线程对象调用了start()方法之后,该线程处于就绪状态。java虚拟机会为其创建方法调用栈和程序计数器,处于这个状态中的线程并没有开始运行,只是表示该线程可以运行了。至于该线程何时开始运行,取决于JVM里线程调度器的调度。

注意:启动线程使用start()方法,而不是run()方法。永远不要调用线程对象的run()方法,调用start()方法来启动线程,系统会把run()方法当成线程执行体来吃处理。但如果直接使用线程对象调用run()方法,系统会把线程对象当成一个普通对象,而run()方法也只是一个普通方法,而不是线程执行体。

二、运行和阻塞状态

运行状态:

如果处于就绪状态的线程获得了CPU,开始执行run()方法的线程执行体,则该线程处于运行状态。

阻塞状态:

当发生如下情况,线程就会进入阻塞状态

  • 线程调用了Thread.sleep(xx)方法占用了处理器资源,此时会进入阻塞状态
  • 线程调了一个阻塞式IO方法,在该方法返回之前,线程被阻塞了
  • 线程试图获得一个同步监听器,但同步监听器正被其他线程所持有
  • 线程在等待某个通知(notify)

当前正在执行的线程被阻塞后,其他线程就可以获得执行的机会。被阻塞的线程会在合适的时候重新进入就绪状态,注意是就绪状态而不是运行状态。也就是说,被阻塞线程的在被解除阻塞之后,必须重新等待线程的调度才可以进入运行状态。

针对上面阻塞的情况,自然会有解除的方法

  • 调用sleep(xx)方法的线程已经过了指定时间
  • 线程调用的阻塞式IO方法已经返回
  • 线程成功获取了线程的同步监听器
  • 线程接受到唤醒的通知


从上面的图可以看出,线程阻塞了只能进入阻塞状态,无法进入运行状态。而就绪和运行状态之间的转换往往不受程序的影响,而是由系统线程调度而 决定的,当线程处于就绪状态,得到CUP的处理资源,就会进入运行状态;当线程运行状态时失去处理器资源时,就会了就绪状态。

三、线程死亡

一般如下情况,线程会进入死亡状态

  • run()或call()方法体执行完毕,线程正常结束
  • 线程抛出一个未捕获的异常(Exception)或错误(Error)
  • 直接调用线程的stop()方法来结束该线程。该方法容易导致死锁,现在该方法已经过时了。

当主线程结束后,其他线程不受任何影响,并不会随之结束。一旦子线程启动起来了,它拥有和主线程同等的地位,不受主线程的影响。

不能对死亡状态的线程再次调用start()方法,start()方法只针对新建状态的线程,否则都会引起IllegaIThreadStateException异常。

猜你喜欢

转载自blog.csdn.net/hzw2017/article/details/80615897