文章目录
前言
体能状态先于精神状态,习惯先于决心,聚焦先于喜好。
从操作系统层面谈线程的状态
进程和线程的简单介绍
在操作系统中,进程是资源分配的基本单位,线程是CPU调度的基本单位
一个进程可以包含多个线程,换句话说,多个线程之间可以共享一个进程占用的硬件资源——当然,具体运行环节,每个线程依旧需要独享一些资源。
进程的资源分配的操作相比线程而言要“重”,或者说要复杂、耗时。
线程之间的切换也是需要消耗一定的性能。
从宝贵的CPU资源来谈线程的状态
在整个计算机的硬件设施中,无论是从价格,还是容量的角度,最宝贵的算是CPU了,所以多线程编程环境下CPU的分配就是一个非常重要的特性。
在操作系统中,进程是资源分配基本单位,线程是CPU调度基本单位。
为了满足多个线程的并发运行,操作系统会为每个线程分配一个时间片,得到时间片的线程可以运行,否则就需要线程进行等待。
进程和线程的状态
线程同样具有就绪、等待、执行三种基本状态,同样具有状态之间的转换关系。
当程序需要使用CPU时,由操作系统给线程分配时间片,在该时间内运行,如果程序中有其它操作(比如I/O操作,等待用户从键盘输入信息),那么操作系统此时会将线程的状态归为阻塞,不分配CPU资源,等到其它操作结束后,从新分配时间片,这个过程可以看出来,在CPU中程序其实是断断续续的执行的。
具体如下图:

Java 的跨平台特性
Java 是跨平台的开发语言,当我们在 Java 代码中使用进行多线程开发的时候,底层需要操作系统的具体实现。因为 JVM 中间隔着一个操作系统,所以 Java 中的线程状态和操作系统的线程状态存在一些不同。
Java 中线程的状态
Java 中并没有进程的概念,而只有线程的概念。
Java 中线程的状态和操作系统中线程的状态有所不同,因为 JVM 只能把相关程序通过本地方法栈,再通过执行引擎传递给操作系统来执行。
Java 中线程的状态有 6 种,可以在 java.lang.Thread 中进行查看。
从下面这张状态转化图可以看出来,JVM 无法完全控制线程是否阻塞,因为在 RUNNABLE 这种状态下,CPU 资源的分配是由操作系统进行的,所以 JVM 中RUNNING 状态 有可能是阻塞的。
再一个,对于Java 中Blocked (阻塞)状态,其表明线程需要等待获得获得再次获得 monitor锁(翻译为控制器锁或内置锁),之所以说再次,因为在 Object.wait()之后,线程需要其他线程调用 Object.notify或者 Object.notifyAll进行唤醒

java.lang.Thread
Thread 类是我们常用的线程类之一,使用它需要重写其中的run()方法。
Thread 实现了 Runnable 接口。
下面是源码中对Thread 的简单介绍:
- thread 表示一个进程中线程的执行。JVM 允许一个应用同时拥有多个线程运行。
- 每一个线程有一个优先级。优先级高的线程会被优先执行。线程允许被设置为 daemon 线程,被设置为 daemon的线程会驻留后台,知道整个程序运行结束才退出。
- 当 JVM 启动的时候,一般而言只会有一个线程(main方法)。对于多线程的情况,JVM会执行所有的线程,直到下面的情况发生:
[1]、Runtime的exit()方法被请求,并通过权限验证
[2]、所有的线程都不是 daemon 线程(后台驻留线程)并且已经死亡;或者已经返回了run()方法的执行结果;或者抛出异常。 - 创建线程的方法有两种(其实不止两种),第一种是继承 Thread 类,第二种是实现 Runnable 接口.
- 每一个线程都有一个名字,如果你在创建时不指定,那么一个新名字会自动生成。
monitor 锁
monitor锁可以被翻译为 控制锁,也叫内置锁,表示所有Java对象自身可以作为同步锁的特性。多线程学习——内置锁(监视器锁)、对象 和 Synchronized 代码块
Java 中线程的状态
参考 java.lang.Thread 中 State 的注释可以得到以下内容
-
Java 中线程一共有6种状态:NEW(新建)、RUNNABLE(运行)、BLOCKED(锁池)、TIMED_WAITING(定时等待)、WAITING(等待)、TERMINATED(终止、结束)
-
Thread.State.NEW(新建):创建了线程,但是没有调用 start()方法。
-
Thread.State.RUNNABLE(正在运行):调用了 start()方法,正在jvm中运行,但是可能正在等待操作系统的其他资源。
-
Thread.State.WAITING(等待):处于等待状态的线程,正在等待另一个线程执行特定的操作,比如 Object.notify()或Object.notifyAll()。
-
Thread.State.TIMED_WAITING(定时等待),线程等待指定的时间后继续执行。
-
Thread.State.BLOCKED(阻塞):等待获取 监视器锁(对象的内置锁),可以是获取synchronized 方法/代码块的监视器锁,也可以是 wait()方法后,等待其他线程唤醒再次获取 synchronized 的方法/代码块 的监视器锁。
-
Thread.State.TERMINATED(结束或死亡):线程运行结束或者死亡。
Java 线程的阻塞和操作系统的阻塞
Java 线程中RUNNING 状态也可能阻塞
上文在图中已经画出了 Java 线程RUNNING 状态需要操作系统分配CPU资源,而CPU调度的过程可能是间歇式阻塞的,比如等待用户I/O.
Java 线程的BLOCKED 阻塞状态
Java 中线程可能处于WAITING、TIMED_WAITING、BLOCKED ,你可能说,大家都是等待,起那么多名字干嘛?
其实根源在于,BLOCKED 是明确没有持有monitor锁的状态,如果想要进入 RUNNING状态,需要获取monitor锁才行。
而 WAITING 和 TIMED_WAITING 状态的线程可能进入 BLOCKED 状态 ,也可能再次直接进入 RUNNING 状态,区别在于命令。
Object.wait()和Object.wait(n)会释放锁,然后进入BLOCKED状态
Thread.sleep(n)不会释放锁,线程状态会由 TIMED_WAITING 再次进入 RUNNING
已经不推荐使用的 Thread.suspend()命令 不会释放锁资源,而是进入 WAITING 状态,等待不推荐使用的 Thread.resume()来从新转化为 RUNNING 状态。
参考资料
[1]、https://www.cnblogs.com/duanjiapingjy/p/9426825.html
[2]、https://www.cnblogs.com/GooPolaris/p/8079490.html
[3]、https://www.cnblogs.com/zbqhc/p/7624372.html
本文详细探讨了Java线程的六种状态,包括NEW、RUNNABLE、BLOCKED、TIMED_WAITING、WAITING和TERMINATED,以及这些状态间的转换。文章还解释了Java线程状态与操作系统线程状态的区别,特别关注了Java中线程阻塞的多种情况,如因等待monitor锁或执行定时等待等。
1920

被折叠的 条评论
为什么被折叠?



