• 操作系统与Java中线程状态的区分


    操作系统中的3种or5种线程状态

    3种

    1. 就绪
    2. 运行
    3. 阻塞
      在这里插入图片描述

    5种

    在这里插入图片描述

    Java中的6种线程状态

    6个状态

    java.lang.Thread类内部维护了一个枚举类State,包含了Java线程的6种状态

    public enum State {
    	//新建
        NEW,
    	//运行
        RUNNABLE,
        //阻塞
        BLOCKED,
        //等待
        WAITING,
    	//超时等待
        TIMED_WAITING,
    	//终止
        TERMINATED;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14

    在这里插入图片描述

    其中的RUNNABLE包括了运行状态就绪状态

    NEW 新建

    new Thread()创建了一个线程,还没有执行start()方法。此时线程状态是NEW

    RUNNABLE 运行

    调用的start(),这个线程会执行它的run()方法,此时进入RUNNABLW状态

    • RUNNABLE 对应了操作系统中线程状态的 Running 和 Ready
      也就是Runnable状态的线程可能正在运行,也可能处于就绪状态
    • 一个正在运行的线程ThreadA,它的状态是Runnable,如果任务没执行完,CPU时间片用完了,调度其他线程,ThreadA的状态还是Runnable,处于就绪态,随时可能被再次执行。

    BLOCKED 阻塞

    在进入synchronized代码块/方法 时,如果线程没有获取到对应的monitor锁,就会从Runnable运行状态进入Blocked阻塞状态

    WAITING 等待

    只有通过synchronized会进入阻塞Blocked
    对于其他锁(ReentrantLock等),如果线程没有获取到锁,会直接进入Waiting状态
    本质就是执行了LockSupport.park()方法进入Waiting状态

    wait()/join()也会进入等待

    BLOCKED阻塞状态 与 WAITING等待状态的区别

    • Blocked:没有获取到monitor锁,进入阻塞,等待其他线程释放monitor锁
    • Waiting:等待某个条件,调用了notify()/notifyAll(),或者join的线程执行完

    TIMED_WAITING 超时等待

    线程会进入超时等待的条件:执行以下带时间参数的方法时

    方法方法签名所属类
    wait(long timeout)public final native void wait(long timeout)Object
    sleep(long millis)public static native void sleep(long millis)Thread
    join(long millis)public final synchronized void join(long millis)Thread
    parkNanos(Object blocker, long nanos)public static void parkNanos(Object blocker, long nanos)LockSupport
    parkUntil(Object blocker, long deadline)public static void parkUntil(Object blocker, long deadline)LockSupport

    LockSupport的park和unpark方法都是调用Unsafe类的本地方法
    在这里插入图片描述

    TERMINATED 终止

    1. run()方法执行完,线程结束
    2. 程序出现异常,意外终止了run()方法

    线程状态的切换

    从 Blocked 进入 Runnable 状态

    Runnable进入Blocked是因为没有获得锁才进入了阻塞;
    所以被阻塞的线程获得其他线程释放的monitor锁后,才可以从Blocked到Runnable

    从 Waiting 进入 Runnable状态

    1. 执行LockSupport.unpark()
    2. join的线程结束
    3. 被中断
    • 如果通过其他线程调用notify()或 notifyAll()来唤醒它,那么它会直接进入Blocked 状态这里需要注意一点,因为唤醒 waiting线程的线程如果调用notify/notifyAll,要求必须先持有该 monitor锁,也就是wait、notify、notifyAll 必须在synchronized 代码块中。

    • 所以处于 waiting 状态的线程被唤醒时拿不到该锁,就会进入 Blocked 状态,直到执行了notify/notifyAll 唤醒它的线程执行完并且释放了 monitor锁,才可能轮到它去尝试获取这把锁,如果它得到了锁,就会从Blocked 状态进入Runnable状态。

    从 TIMED_WAITING进入 Runnable状态

    1. 通过notify/notifyAll先进入阻塞Blocked,获取到锁后,再进入Runnable状态
    2. 超过设置的等待时间后,就会自动获取锁,直接进入Runnable
      join线程执行完 / LockSupport.unpark() / 被中断 都会直接进入Runnable不会经历Blocked阻塞
  • 相关阅读:
    用C#也能做机器学习?
    (附源码)springboot炼糖厂地磅全自动控制系统 毕业设计 341357
    工业设计能做出什么独特优势?
    03基于 Vue2.x 的 Vuex3.x .
    Android RecyclerView 之 吸顶效果
    牛血清白蛋白-乳酸-羟乙酸共聚物 PLGA-BSA(bovine serum albumin)
    “充钱”也难治快手的“亏亏亏”?
    2.10 - 存储管理 2.11 - 页式存储 2.12 - 段式存储 2.13 - 段页式存储
    fastgpt本地详细部署以及配置
    HCIA VLAN间通信 多臂路由与单臂路由
  • 原文地址:https://blog.csdn.net/lanleihhh/article/details/125396444