• JAVA多线程技术-线程的生命周期


    当线程被创建并启动后,它既不是一启动就进入了执行状态,也不是一直处于执行状态,在线程的生命周期中,它要经过新建(New)、就绪(Ready)、运行(Running)、阻塞(Blocked)、和死亡(Dead)5种状态。

    尤其是当线程启动以后,它不可能一直“霸占”着CPU独自运行,所以CPU需要在多条线程之间切换,于是线程状态也会多次在运行和就绪状态间切换。

    在这里插入图片描述

    1、新建状态(New)

    使用new关键字创建了线程之后,该线程处于新建状态,此时线程对象不能运行, 和其他Java 对象一样, 仅仅由Java 虚拟机分配了内存, 并初始化成员变量的值。没有表现出任何线程的动态特征。程序不会执行线程的线程执行体(run方法内的内容)。

    2、就绪状态(Runnable)

    当线程对象调用了start() 方法后, 该线程即进入就绪状态, java虚拟机会为其创建方法调用栈和程序计数器,这个状态的线程并没有开始运行,只是表示该线程可运行了,此线程进入可运行池中, 等待CPU的资源。什么时候运行,取决于JVM的线程调度器的调度。

    注意:启动线程用start() 而不是run(),直接调用run方法的话和调用普通方法一样。

    3、运行状态(Running)

    处于就绪状态的线程获得CPU使用权后, 开始执行run() 方法中的线程执行体, 则该线程处于运行状态。

    当计算机只有一个CPU时,任何时候只有一个线程在运行。当计算机有多个CPU时,将会有多个线程并行,若线程数大于CPU数时,依然存在多个线程在同一个CPU上轮换的现象。

    当底层平台采用抢占式策略时,每一个线程都会获得一小段时间来处理任务,当时间用完后,会让出CPU让其他线程执行,在选择下一个线程时会考虑优先级。手机或一些小型设备采用协作式调度策略,一个线程会一直占用资源,只有调用了sleep()或yield()后才会放弃占用的资源,也就是必须主动放弃。

    注意: 只有处于就绪状态的线程才可能进入运行状态。

    4、阻塞状态(Blocked)

    正处于运行状态的线程遇到某些特殊情况时, 会放弃CPU使用权, 进入阻塞状态。当引起特殊情况的原因被解除后, 线程进入就绪状态, 回到可运行池中, 重新等待系统调度 的CPU使用权。

    下面是从运行状态进入阻塞状态:

    (1)线程调用了sleep()方法主动放弃所占用的处理器资源。

    (2)线程调用了阻塞IO(write或read),在返回之前线程阻塞。

    (3)线程调用同步监视器,若被其他线程持有,则阻塞。

    (4)线程在等待某个通知notify()。

    (5)程序调用了线程的suspend()方法挂起。该方法会造成死锁,尽量避免。

    下面是从阻塞状态进入就绪状态:

    (1)调用sleep的方法的线程经过了指定时间。

    (2)阻塞IO方法返回。

    (3)取得同步监视器。

    (4)线程在等待某个通知,其他线程发出通知。

    (5)挂起状态的线程被调用了resume()恢复方法。

    5、死亡状态(Terminated)

    下面三种方法,线程会进入四忙状态:

    (1)当run() 或call()方法执行完毕,线程政策结束。

    (2)线程抛出一个未捕获的异常 或者 错误的时候(Exception或Error)。

    (3)直接调用线程stop()方法,不建议,会造成死锁。

    进入死亡状态的线程不再拥有运行的资格, 也不能转换到其他状态。

    不要试图对死亡的线程调用start,只有新建状态才能调用start().

    新建状态的线程调用两次start()也会报IllegalThreadStateException错误。

  • 相关阅读:
    【算法随笔:HDU 3333 Turing tree】(线段树 | 离线 | 离散化 | 贪心)
    我是如何写作的?
    青少年python系列 34.内建函数
    mysql的变量
    Android从一个APP跳转到另外一个APP
    大中型园区网络拓扑架构
    微信小程序——Git版本管理
    另类终端「GitHub 热点速览 v.22.15」
    【应用层协议】初始Http,fiddler的使用
    视频录制后怎么裁剪?这里有可以学习的操作
  • 原文地址:https://blog.csdn.net/zhangzijiejiayou/article/details/125902877