编程知识 cdmana.com

Java线程状态及切换

Java线程状态及切换

一、什么是Java线程状态

在Java程序中,用于描述Java线程的六种状态:

  • 新建(NEW):当前线程,刚刚新建出来,尚未启动。
  • 运行(RUNNABLE):当前线程,处于竞争CPU时间分片或已经获得CPU时间片的状态。
  • 等待(WAITTING):当前线程,处于休眠,不参与CPU时间片竞争的状态。
  • 定时等待(TIMED_WAITTING):当前线程,处于定时休眠,暂时不参与CPU时间片竞争的状态。
  • 阻塞(BLOCKED):当前线程,处于阻塞,不参与CPU时间片竞争的状态。
  • 终止(TERMINATED):当前线程,处于最终停止的状态。

新建状态,只能进入运行状态。而终止状态无法再转为其他状态。

等待/定时等待与阻塞,差别就是后者需要一个事件信号(如其他线程放弃当前线程需要的排他锁),才可以进行状态切换。当然,强行关闭也是可以的。

Java线程的实现并不受JVM规范约束,故不同虚拟机的实现,往往不同。目前主流的HotSpot是将每个Java线程直接映射到一个操作系统的原生线程,从而由操作系统完成一系列的线程调度

二、哪里看Java线程状态

查看Java线程状态,主要存在三种方式:

  • java.lang.Thread.State下可以直接看到Java的六种线程状态
  • Java运行时,程序内部可以通过Thread.getState()获取目标线程状态
  • Java运行时,程序外部可以通过jstack等工具,查看线程状态

有关jstack等工具等使用,后续会有博客,专门阐述。

三、什么时候变换Java线程状态

Java线程状态的切换嘛。不啰嗦,直接上图。
在这里插入图片描述
这张图涵盖了Java线程状态切换的各类方法。相较网上一些图片,更为详尽一些。
如果有所遗漏,可以告诉我,我会及时填补上。

四、谁在使用Java线程状态

日常开发中,我们并不会直接与线程状态进行交互。
我们往往直接使用JDK包装好的工具,如JUC包下的各类工具等。

举个栗子

线程池中的应用

位置:com.sun.corba.se.impl.orbutil.threadpool.ThreadPoolImpl#close

 // Note that this method should not return until AFTER all threads have died. public void close() throws IOException {  // Copy to avoid concurrent modification problems.  List<WorkerThread> copy = null;  synchronized (workersLock) {   copy = new ArrayList<>(workers);  }  for (WorkerThread wt : copy) {   wt.close();   while (wt.getState() != Thread.State.TERMINATED) {    try {     wt.join();    } catch (InterruptedException exc) {     wrapper.interruptedJoinCallWhileClosingThreadPool(exc, wt, this);    }   }  }  threadGroup = null; }

实际查看JDK后发现,JDK中其实也没有辣么多的实例,并且大多数直接关联线程状态的,也是一些状态查看的东东。
这在文章开头就说,Java线程操作,是很底层的,甚至其实现都不包含在虚拟机规范中。
主流的HotSpot,也是直接将Java线程映射到系统线程,由系统进行一系列的线程调度处理。
所以,在JDK中,是直接对线程状态进行处理的部分是很少的。

五、为什么需要线程状态

1.为什么需要线程状态这一概念

这个问题,可以从两个角度来说明:生命周期与资源管理

  • 一方面,线程状态很好地刻画了线程的整个生命周期,对生命周期中不同阶段进行了有效划分。
  • 另一方面,资源是有限的,需求是无限的。所以需要将系统资源有意识地进行调度,合理利用比较优势,追求帕累托最优。

实现后者的,就是利用线程在生命周期的不同阶段这一天然属性带来的状态刻画,进行的分组。CPU调度只需要关注运行状态的线程。而阻塞,等待等线程,都有着属于自己的一套处理方式。最终获得资源(开发时对复杂性的应对,运行时对系统资源对消耗,应用者心智模型的成长等)的优化分配。

2.JDK中为什么需要定义Java线程状态

前文有说到,Java中很少直接使用到线程状态。那么为什么还要在JDK中定义Java的六种线程状态呢?
一方面,通过信息透明的方式,降低使用者使用时建立心智模型的成本。如,现在的我们可以通过打印日志,打断点,快速了解Java的各个线程状态,并清楚了解产生的原因。从而大大提高了我们对Java线程的认识,进而更为愉快地拥抱JUC包下诸如线程池等工具。
另一方面,通过可以直接应用的状态枚举,我们可以很好地对现有工具进行二次开发等。如我们可以通过扩展AQS,并在其中添加线程状态的校验,从而得到定制化的线程同步工具。

六、如何使用线程状态

使用的方式,我已经在上文说了:学习Java线程,定制线程相关工具开发。
这里给出一个有关线程学习的demo:

/** * @program: learning * @description: 用于确认线程状态问题 * @author: Jarry * @create: 2020-10-26 22:25 **/public class ThreadState { public static void main(String[] args) {  threadStateTest();//  threadStateTest2();//  threadStateWithBlocked();//  threadStateWithException();//  threadStateWithSuspend(); } /**  * 实践证明:Thread.suspend()与Thread.resume()不会改变线程状态  * 线程状态该是Waiting,就Waiting。该Timed_Waiting就Timed_Waiting  * Thread.suspend()与Thread.resume()只是挂起目标线程(并且不会释放锁资源)  */ private static void threadStateWithSuspend() {  Thread thread1 = new Thread(() -> {//   LockSupport.park();   LockSupport.parkNanos(2000000000);  });  thread1.start();  printThreadState(thread1);  LockSupport.parkNanos(500000000);  printThreadState(thread1);  thread1.suspend();  printThreadState(thread1);  LockSupport.parkNanos(500000000);  printThreadState(thread1);  thread1.resume();  LockSupport.parkNanos(500000000);  printThreadState(thread1);//  LockSupport.unpark(thread1); } /**  * 展现线程阻塞状态  */ private static void threadStateWithBlocked() {  Runnable runnable = new Runnable() {   @Override   public void run() {    synchronized (ThreadState.class) {//     LockSupport.parkNanos(2000000000);     LockSupport.park();    }   }  };  Thread thread1 = new Thread(runnable);  Thread thread2 = new Thread(runnable);  thread1.start();  LockSupport.parkNanos(500000000);  thread2.start();  // 加上以下时间间隔,则结果:Runnable->Blocked  // 推论:Thread.start()会将线程状态设置为Runnable,然后在遇到sync的锁,再切换为Blocked状态//  LockSupport.parkNanos(500000000);  printThreadState(thread2);  LockSupport.parkNanos(500000000);  printThreadState(thread2);  LockSupport.parkNanos(500000000);  LockSupport.unpark(thread1);  LockSupport.unpark(thread2); } /**  * 由.........

版权声明
本文为[程序猿欧文]所创,转载请带上原文链接,感谢
https://my.oschina.net/mikeowen/blog/4712143

Scroll to Top