面试官问:为什么Java线程没有Running状态?我...
共 6366字,需浏览 13分钟
·
2020-08-18 01:18
什么是 RUNNABLE?
一个在 JVM 中执行的线程处于这一状态中。(A thread executing in the Java virtual machine is in this state.)
注:这里的进程指早期的单线程进程,这里所谓进程状态实质就是线程状态。
与传统的ready状态的区别
处于 runnable 状态下的线程正在 Java 虚拟机中执行,但它可能正在等待来自于操作系统的其它资源,比如处理器。 A thread in the runnable state is executing in the Java virtual machine but it may be waiting for other resources from the operating system such as processor.
甚至还可能有包括上图中的 waiting 状态的部分细分状态,在后面我们将会看到这一点。
与传统的running状态的区别
更复杂的可能还会加入优先级(priority)的机制。
注:如果期间进行了 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 之类的状态。
---END--- 重磅!码农突围-技术交流群已成立
扫码可添加码农突围助手,可申请加入码农突围大群和细分方向群,细分方向已涵盖:Java、Python、机器学习、大数据、人工智能等群。 一定要备注:开发方向+地点+学校/公司+昵称(如Java开发+上海+拼夕夕+猴子),根据格式备注,可更快被通过且邀请进群
▲长按加群
推荐阅读
• 卧槽!微信居然有“隐身功能”了! • 认真看看, 以后写 SQL 就爽多了:MyBatis 动态 SQL • 我在谷歌,女友在亚马逊,晒出2人总收入,网友:好酸 • 为什么建议大家使用 Linux 开发?爽(外加七个感叹号) • SQL语句大全,所有的SQL都在这里 • 太牛了!98 年后浪科学家,首次挑战图片翻转不变性假设,一作拿下 CVPR 最佳论文提名 最近面试BAT,整理一份面试资料《Java面试BAT通关手册》,覆盖了Java核心技术、JVM、Java并发、SSM、微服务、数据库、数据结构等等。 获取方式:点“在看”,关注公众号并回复 BAT 领取,更多内容陆续奉上。
如有收获,点个在看,诚挚感谢明天见(。・ω・。)ノ♡
---END--- 重磅!码农突围-技术交流群已成立
扫码可添加码农突围助手,可申请加入码农突围大群和细分方向群,细分方向已涵盖:Java、Python、机器学习、大数据、人工智能等群。 一定要备注:开发方向+地点+学校/公司+昵称(如Java开发+上海+拼夕夕+猴子),根据格式备注,可更快被通过且邀请进群
▲长按加群
推荐阅读
• 卧槽!微信居然有“隐身功能”了! • 认真看看, 以后写 SQL 就爽多了:MyBatis 动态 SQL • 我在谷歌,女友在亚马逊,晒出2人总收入,网友:好酸 • 为什么建议大家使用 Linux 开发?爽(外加七个感叹号) • SQL语句大全,所有的SQL都在这里 • 太牛了!98 年后浪科学家,首次挑战图片翻转不变性假设,一作拿下 CVPR 最佳论文提名 最近面试BAT,整理一份面试资料《Java面试BAT通关手册》,覆盖了Java核心技术、JVM、Java并发、SSM、微服务、数据库、数据结构等等。 获取方式:点“在看”,关注公众号并回复 BAT 领取,更多内容陆续奉上。
如有收获,点个在看,诚挚感谢明天见(。・ω・。)ノ♡
最近面试BAT,整理一份面试资料《Java面试BAT通关手册》,覆盖了Java核心技术、JVM、Java并发、SSM、微服务、数据库、数据结构等等。 获取方式:点“在看”,关注公众号并回复 BAT 领取,更多内容陆续奉上。