线程状态

217 阅读3分钟

线程有哪些状态,对于这个问题,有些说五种,有些说六种。各有各的说法。我们一次来说明一下

  • NEW: 新建
  • RUNNABLE:可运行
  • TERMINATED:终止
  • BLOCKED:阻塞
  • WAITING:等待
  • TIMED_WAITING:有时限的等待

我们来分别细细说说每种状态的产生,和他们之间的转换

NEW -> RUNNBALE -> TERMINATED

(new)新建状态,这时 只时单纯new了一个Thread对象,这时仅仅是Java对象,并没有跟操作系统底层的线程所关联,并不会被分配cpu。当调用线程的start方法是,就会由新建状态转为RUNNABLE状态,这时这个线程真正的关联了底层的线程,这时才会被cpu执行。当执行完run方法时,线程就会由RUNNABLE转为TERMINATED终止状态。 这三种状态 是顺时针进行的,不可逆转,也就是 不会由 TERMINATED变为RUNNABLE,RUNNABLE也不会变为NEW状态。

RUNNABEL <=> BlOCKED

什么时候会变为BLOCKED状态。当多个线程争抢同一把锁时,只有一个线程可以持有锁,而其他线程则由RUNNABLE变为BLOCKED。当持有锁的线程释放锁后,处于BLOCKED的线程去争抢锁,争抢到锁的由BLOCKED状态转为RUNNABLE状态。

RUNNABLE => WAITING = > BLOCKED

当线程在获取锁之后,执行过程中 发现有条件没有满足,不能往下执行,这时不能一直占着锁,所以使用wait()方法来讲锁释放,并由RUNNABLE状态转为WAITING状态。 当其他线程调用notify()或者notifyAll()的方法时,就会唤醒等待的线程,让WAITING状态的线程转为BLOCKED 重新去竞争锁。

RUNNABLE => TIMED_WAITING

第一种:当调用wait(long time) 有时间的方法时,会在时间到了或者被主动唤醒时再去争抢锁

第二种:通过sleep(long time)这种方式,可以不用放在锁内,即使放在锁内,也不会释放锁,当时间到的时候会重新变为RUNNABLE状态。

2.在操作系统层面的五种线程状态

1.新建。

2.就绪。

3.运行。

4.阻塞

5.终止

通过对比发现,操作系统层面 把RUNNABLE进行了再细分,把BLOCKED和WAITING和TIMED_WAITING 一起划分为了阻塞状态。但多了个io操作,也属于阻塞层面,这是为什么。是因为再进行io对磁盘的读写的时候,并不需要cpu为其分配时间片进行操作,所以对于操作系统而言,也就把io操作归为阻塞状态。

这时就有问题,那Java层面的io操作属于什么层面。 在Java层面的io操作属于RUNNABLE状态,因为当线程调用阻塞式 API,线程进入休眠状态,这里指的是操作系统层面的。从 JVM 层面,Java 线程状态依然处于 RUNNABLE 状态。JVM 并不关心操作系统线程实际状态。从 JVM 看来等待 CPU 使用权(操作系统线程状态为可运行状态)与等待 I/O (操作系统线程状态处于休眠状态)没有区别,都是在等待某种资源,所以都归入 RUNNABLE 状态。

开启掘金成长之旅!这是我参与「掘金日新计划 · 2 月更文挑战」的第 6 天,点击查看活动详情