为什么 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阻塞时 如 ...
随机推荐
- pt-archiver使用记录
pt-archiver使用记录 功能:将MySQL表中的行存档到另一个表或文件中用法:pt-archiver [OPTIONS] --source DSN --where WHERE ; trunca ...
- 【leetcode】1229.Meeting Scheduler
题目如下: 你是一名行政助理,手里有两位客户的空闲时间表:slots1 和 slots2,以及会议的预计持续时间 duration,请你为他们安排合适的会议时间. 「会议时间」是两位客户都有空参加,并 ...
- DevOps之持续集成Pipeline(一)
一.Pipeline介绍 Jenkins2.0中最大的一个特性就是Pipeline,实际使用中Pipeline已经超越了我们对jenkins本身的理解,可能在之前我们大多数把Jenkins当做 ...
- java.lang.IllegalArgumentException: java.io.IOException: Alias name [tomcat] does not identify a key entry
java.lang.IllegalArgumentException: java.io.IOException: Alias name [tomcat] does not identify a key ...
- 简单配置prometheus
一,物理节点安装配置(简单配置,未涉及报警及grafana图形展示) 1,prometheus 官网下载安装 下载安装 # pwd /usr/local/src https://github.com/ ...
- java总结1
栈,堆,方法区.main和局部变量在栈,new 对象 在堆, 类和常量在方法区除了8大基础数据类型,其他都为引用变量局部变量在函数内或方法上声明,没有默认值,定义必须赋值一旦提供构造方法,就不会有默认 ...
- NOIP2018 D1T3赛道修建
题目链接:Click here Solution: 最小值最大,考虑二分一个答案\(k\) 考虑在子树内先匹配,最后传递一个值给自己的父亲(因为每条边只能用一次,所以一颗子树最多传递一个值) 那么我们 ...
- 2019.9.16JAVA课堂作业
public class TestDouble { public static void main(String args[]) { System.out.println(&qu ...
- 技术干货:Python解析CSV
1. 什么是CSV CSV(Commma-Separated Value)是都好分隔符,其文件以纯文本形式存储表格数据(数字和文本). 案例: 2. 为什么要使用CSV 与专有的二进制文件格式截然不同 ...
- Apache配置详解(最好的APACHE配置教程)
From: http://aiks.blog.com.cn/archives/2006/1748482.shtml Apache的配置 Apache的配置由httpd.conf文件配置,因此下面的配置 ...