为什么 Java 线程没有 Running 状态?
什么是 RUNNABLE?
直接看它的 Javadoc 中的说明:
一个在 JVM 中执行的线程处于这一状态中。(A threadexecuting in the Java virtual machine is in this state.)
而传统的进(线)程状态一般划分如下:
与传统的ready状态的区别
更具体点,javadoc 中是这样说的:
处于 runnable 状态下的线程正在 Java 虚拟机中执行,但它可能正在等待来自于操作系统的其它资源,比如处理器。
A thread in the runnable state is executing in the Java virtual machine but it may be waiting forother resources from the operating system such as processor.
显然,runnable 状态实质上是包括了 ready 状态的。
甚至还可能有包括上图中的 waiting 状态的部分细分状态,在后面我们将会看到这一点。
与传统的running状态的区别
更复杂的可能还会加入优先级(priority)的机制。
这个时间分片通常是很小的,一个线程一次最多只能在 cpu 上运行比如10-20ms 的时间(此时处于 running 状态),也即大概只有0.01秒这一量级,时间片用后就要被切换下来放入调度队列的末尾等待再次调度。(也即回到 ready 状态)
注:如果期间进行了 I/O 的操作还会导致提前释放时间分片,并进入等待队列。又或者是时间分片没有用完就被抢占,这时也是回到 ready 状态。
不计切换开销(每次在1ms 以内),相当于1秒内有50-100次切换。事实上时间片经常没用完,线程就因为各种原因被中断,实际发生的切换次数还会更多。
时间分片也是可配置的,如果不追求在多个线程间很快的响应,也可以把这个时间配置得大一点,以减少切换带来的开销。
如果是多核CPU,才有可能实现真正意义上的并发,这种情况通常也叫并行(pararell),不过你可能也会看到这两词会被混着用,这里就不去纠结它们的区别了。
当你看到监控上显示是 running 时,对应的线程可能早就被切换下去了,甚至又再次地切换了上来,也许你只能看到 ready 与 running 两个状态在快速地闪烁。
当然,对于精确的性能评估而言,获得准确的 running 时间是有必要的。
我们将看到,Java 线程状态的改变通常只与自身显式引入的机制有关。
当I/O阻塞时
与 cpu 正打得火热的线程可能不情愿听到这一中断信号,因为它意味着这一次与 cpu 缠绵的时间又要到头了……奴为出来难,何日君再来?
@Test
public void testInBlockedIOState() throws InterruptedException {
Scanner in = new Scanner(System.in);
// 创建一个名为“输入输出”的线程t
Thread t = new Thread(new Runnable() {
@Override
public void run() {
try {
// 命令行中的阻塞读
String input = in.nextLine();
System.out.println(input);
} catch (Exception e) {
e.printStackTrace();
} finally {
IOUtils.closeQuietly(in);
}
}
}, "输入输出"); // 线程的名字
// 启动
t.start();
// 确保run已经得到执行
Thread.sleep(100);
// 状态为RUNNABLE
assertThat(t.getState()).isEqualTo(Thread.State.RUNNABLE);
}
@Test
public void testBlockedSocketState() throws Exception {
Thread serverThread = new Thread(new Runnable() {
@Override
public void run() {
ServerSocket serverSocket = null;
try {
serverSocket = new ServerSocket(10086);
while (true) {
// 阻塞的accept方法
Socket socket = serverSocket.accept();
// TODO
}
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
serverSocket.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}, "socket线程"); // 线程的名字
serverThread.start();
// 确保run已经得到执行
Thread.sleep(500);
// 状态为RUNNABLE
assertThat(serverThread.getState()).isEqualTo(Thread.State.RUNNABLE);
}
至少我们看到了,进行传统上的 IO 操作时,口语上我们也会说“阻塞”,但这个“阻塞”与线程的 BLOCKED 状态是两码事!
如何看待RUNNABLE状态?
JVM 并不关心底层的实现细节,什么时间分片也好,什么 IO 时就要切换也好,它并不关心。
你用嘴,用手,还是用什么鸟东西来满足它的需求,它并不关心~
就好比前台或保安坐在他们的位置上,可能没有接待什么人,但你能说他们没在工作吗?
比如 synchronize 机制有可能让线程进入BLOCKED 状态,sleep,wait等方法则可能让其进入 WATING 之类的状态。
RUNNABLE 状态对应了传统的 ready, running 以及部分的 waiting 状态。
作者:国栋,来源:http://rrd.me/ekN5T
2、
3、
4、
5、
点击「阅读原文」和栈长学更多~
为什么 Java 线程没有 Running 状态?的更多相关文章
- Java线程Thread的状态解析以及状态转换分析 多线程中篇(七)
线程与操作系统中线程(进程)的概念同根同源,尽管千差万别. 操作系统中有状态以及状态的切换,Java线程中照样也有. State 在Thread类中有内部类 枚举State,用于抽象描述Java线程的 ...
- java线程五种状态
java线程五种状态: 创建 -> 就绪 -> 运行 -> 销毁 创建 -> 就绪 -> 运行 -> 等待(缺少资源) -> 销毁 下图:各种状态转换
- java线程的五大状态,阻塞状态详解
一.状态简介 一个线程的生命周期里有五大状态,分别是: 新生 就绪 运行 死亡 运行后可能遇到的阻塞状态 二.相关方法 2.1 新生状态 Thread t = new Thread(); 正如我们前面 ...
- java线程四种状态
一个线程可以有四种状态: 1.新(new), 即线程刚刚创建,而并未执行 2.可运行(runnable),意味着一旦时间分片机制有空闲的CPU周期提供给一个线程,那个线程便可立即开始运行.因此,线程可 ...
- JAVA线程间的状态转换
线程间的状态转换: 1. 新建(new):新创建了一个线程对象. 2. 可运行(runnable):线程对象创建后,其他线程(比如main线程)调用了该对象的start()方法.该状态的线程位于可运 ...
- Java线程的六种状态
java线程有很多种状态,最主要的有六种,被创建.运行.睡眠.等待.阻塞以及消亡六种,也有很多归结为5种,把睡眠以及等待归结为冻结: 被创建:就是线程被创建,就是new thread()之后就是创建一 ...
- Java-技术专区-如何监控Java线程池的状态
线程池介绍 什么是线程池.线程池核心类.线程池工作流程.线程池分类.拒绝策略.及如何提交与关闭线程池等. 但在实际开发过程中,在线程池使用过程中可能会遇到各方面的故障,如线程池阻塞,无法提交新任务等. ...
- java线程控制、状态同步、volatile、Thread.interupt以及ConcurrentLinkedQueue
在有些严格的系统中,我们需要做到干净的停止线程并清理相关状态.涉及到这个主题会带出很多的相关点,简单的总结如下: 我们知道,在java中,有一个volatile关键字,其官方说明(https://do ...
- 为什么JAVA线程中没有Running状态?
面试官问:为什么 Java 线程没有 Running 状态?我懵了 —— 转 芋道源码 什么是 RUNNABLE? 与传统的ready状态的区别 与传统的running状态的区别 当I/O阻塞时 如 ...
随机推荐
- 初始Turtle
---恢复内容开始--- turtle库介绍 海龟作图最初源自20世纪60年代的Logo(创建于1967年,是一种教育编程语言)编程语言. 常用函数说明 画笔的属性 设置画笔的宽度 t.pensi ...
- IOS上编译boost库
环境:xcode9mac os 10.13 1.下载boost库并解压2.cd到解压后的文件包内,执行 sh bootstrap.sh(解压后会得到这个脚本文件).3.执行./b2 编译整个库.4.经 ...
- linux常用的镜像(centos、kali、redhat等)官方下载地址
常用的linux版本: Redhat:https://developers.redhat.com/topics/linux/ Centos:https://www.centos.org/downloa ...
- css-div中文字过多(内容超出div宽度)后自动换行
故事是这样的: 买家秀:(refuse) ...
- 关于 ATL 中 CComControl 的构造
分享一篇 C++语言 & ATL 的高阶解读笔记,你需要在C++语言特性中上串下跳,应该算篇有质量的文章. class ATL_NO_VTABLE CHello : // ... public ...
- Java课堂动手动脑
1.使用Files. walkFileTree()找出指定文件夹下所有大于指定大小(比如1M)的文件: 代码: package test; import java.io.IOException; im ...
- sqli-labs(31)
0x01找闭合 这里是WAF的jsp调到php的同样 第二个参数构造 偷看源码 闭合是") 我们尝试一下构造爆破数据库名 login.php?id=&id=-") unio ...
- 大哥带的mssql注入拿shell
任务二 注入点拿shell 路径的爆破 https://blog.csdn.net/edu_aqniu/article/details/78409451 0X01判断 是否为判断当前数据库用户名是否为 ...
- ASP.NET中调用百度地图API
1.打开链接http://developer.baidu.com/map/jshome.htm这里有很多DEMO,或者你直接百度搜索“百度地图API”,第一个就是.进入后有很多方向供你选择,由于现在开 ...
- htonl(),htons(),ntohl(),ntons()--大小端模式转换函数
不同机器内部对变量的字节存储顺序不同,有的采用大端模式(big-endian),有的采用小端模式(little-endian). 大端模式是指高字节数据存放在低地址处,低字节数据放在高地址处. 小端模 ...