并发基础篇(四): 深入浅出java线程的状态

一、线程的五种状态

线程的生命周期可以大致分为5种,但这种说法是比较旧的一种说法,有点过时了,或者更确切的来说,这是操作系统的说法,而不是java的说法。但对下面所说的六种状态的理解有所帮助,所以也写出来,作为参考。

1. NEW: 线程的新建状态,是指通过New关键字创建了Thread类(或其子类)的对象。

2. RUNNABLE: 这种情况指的是Thread类的对象调用了start()方法,这时的线程就等待时间片轮转到自己这,以便获得CPU;第二种情况是线程在处于RUNNABLE状态时并没有运行完自己的run方法,时间片用完之后回到RUNNABLE状态;还有种情况就是处于BLOCKED状态的线程结束了当前的BLOCKED状态之后重新回到RUNNABLE状态。

3. RUNNING: 这时的线程指的是获得CPU的RUNNABLE线程,RUNNING状态是所有线程都希望获得的状态。

4. DEAD: 处于RUNNING状态的线程,在执行完run方法之后,或者异常退出时,就变成了DEAD状态了。

5. BLOCKED: 这种状态指的是处于RUNNING状态的线程,出于某种原因,比如调用了sleep方法、等待用户输入等而让出当前的CPU给其他的线程。

注意: BLOCKED状态,包括三种类型状态:等待(wait)、睡眠(sleep)、阻塞(申请资源:I\O、对象的锁);

二、线程的六种状态

  在java中,线程的状态其实是六种,对应着枚举类型 Thread.State 的六个枚举常量:NEWBLOCKEDRUNNABLEWAITINGTIMED_WAITINGTERMINATED

1. NEW : 新建状态,至今尚未启动的线程的状态。

1 static void NEW() {
2          Thread t = new Thread ();//也就是可以理解为刚刚创建thread
3         System. out.println(t.getState());
4    }

2. BLOCKED: 阻塞状态,受阻塞并且正在等待监视器锁的某一线程的线程状态。

 1private static void BLOCKED() {
 2         final Object lock = new Object();
 3         Runnable run = new Runnable() {
 4              @Override
 5              public void run() {
 6                  for(int i=0; i<Integer.MAX_VALUE; i++){
 7                       synchronized (lock) {
 8                          System. out.println(i);
 9                      }
10                 }
11             }
12         };
13         Thread t1 = new Thread(run);
14         t1.setName( “t1”);
15         Thread t2 = new Thread(run);
16         t2.setName( “t2”);
17         t1.start();
18         t2.start();
19    }

3. RUNNABLE: 可运行线程的线程状态。这里其实合并了两种状态(RUNNING、RUNABLE)

 1private static void RUNNABLE() {
 2         Thread t = new Thread(){
 3              public void run(){
 4                  for(int i=0; i<Integer.MAX_VALUE; i++){
 5                      System. out.println(i);
 6                 }
 7             }
 8         };
 9         t.start();
10    }

当线程调用了start()方法之后,就是运行状态了。

4. WAITING : 等待状态,表示线程进入状态。进入此状态后,会无限等待,直到其他线程做出一些特定的动作(唤醒通知、中断通知)才会再次运行。

 1 private static void WAITING() {
 2          final Object lock = new Object();
 3         Thread t1 = new Thread(){
 4              @Override
 5              public void run() {
 6                  int i = 0;
 7                  while(true ){
 8                       synchronized (lock) {
 9                           try {
10                               lock.wait();//调用这个方法,进入等待状态
11                          } catch (InterruptedException e) {
12                          }
13                          System. out.println(i++);
14                      }
15                 }
16             }
17         };
18         Thread t2 = new Thread(){
19              @Override
20              public void run() {
21                  while(true ){
22                       synchronized (lock) {
23                           for(int i = 0; i< 10000000; i++){
24                              System. out.println(i);
25                          }
26                          lock.notifyAll();
27                      }
28                 }
29             }
30         };
31         t1.setName( “^^t1^^”);
32         t2.setName( “^^t2^^”);
33         t1.start();
34         t2.start();
35    }

5. TIMED_WAITING : 计时等待状态,此状态与 WAITING 状态有些类似,但它是有时间限制的,即只会等待一段指定的时间,当时间到来前,没有被唤醒或或中断,那么时间到来了,就自动"醒来",进入RUNNABLE状态。

1synchronized (lock) {
2   try {
3      lock.wait(60 * 1000L);//只会等待一段指定的时间,当时间到来前,没有被唤醒或或中断
4   } catch (InterruptedException e) {
5   }
6   System. out .println(i++);
7 }

6. TERMINATED : 终止状态,已终止线程的线程状态。

 1 private static void TERMINATED() {
 2         Thread t1 = new Thread();
 3         t1.start();
 4         System. out.println(t1.getState());
 5          try {
 6             Thread. sleep(1000L);
 7         } catch (InterruptedException e) {
 8         }
 9         System. out.println(t1.getState());
10    }

三、线程的状态转换

图片来源网络,如有侵权,删

  • 当一个线程执行了start方法后,不代表这个线程就会立即被执行,只代表这个线程处于可运行的状态,最终由OS的线程调度来决定哪个可运行状态下的线程被执行。
  • 一个线程一次被选中执行是有时间限制的,这个时间段叫做CPU的时间片,当时间片用完但线程还没有结束时,这个线程又会变为可运行状态,等待OS的再次调度;在运行的线程里执行Thread.yeild()方法同样可以使当前线程变为可运行状态。
  • 在一个运行中的线程等待用户输入、调用Thread.sleep()、调用了其他线程的join()方法,则当前线程变为阻塞状态。
  • 阻塞状态的线程用户输入完毕、sleep时间到、join的线程结束,则当前线程由阻塞状态变为可运行状态。
  • 运行中的线程调用wait方法,此线程进入等待队列。
  • 运行中的线程遇到synchronized同时没有拿到对象的锁标记、等待队列的线程wait时间到、等待队列的线程被notify方法唤醒、有其他线程调用notifyAll方法,则线程变成锁池状态。
  • 锁池状态的线程获得对象锁标记,则线程变成可运行状态。
  • 运行中的线程run方法执行完毕或main线程结束,则线程运行结束。

原文发布于微信公众号 - 好好学java(SIHAIloveJAVA)

原文发表时间:2018-06-19

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏企鹅号快讯

Python编写渗透工具学习笔记二

1 用pxssh暴力破解ssh密码 因为默认情况下只有linux有ssh服务,所以此脚本只适用于在linux下使用 靶机 10.10.10.128 kali6...

1906
来自专栏蓝天

C/C++常见gcc编译链接错误解决方法

用“-Wl,-Bstatic”指定链接静态库,使用“-Wl,-Bdynamic”指定链接共享库,使用示例: -Wl,-Bstatic -lmysq...

2223
来自专栏coder修行路

关于java中死锁的总结

关于死锁,估计很多程序员都碰到过,并且有时候这种情况出现之后的问题也不是非常好排查,下面整理的就是自己对死锁的认识,以及通过一个简单的例子来来接死锁的发生,自己...

1180
来自专栏大内老A

ASP.NET Web API自身对CORS的支持: EnableCorsAttribute特性背后的故事

从编程的角度来讲,ASP.NET Web API针对CORS的实现仅仅涉及到HttpConfiguration的扩展方法EnableCors和EnableCor...

20710
来自专栏JavaQ

深入理解Spring系列之十二:@Transactional是如何工作的

结合Spring框架,在进行数据库操作的时候,经常使用@Transactional注解,工作经历中看到很多人使用方式都是错误的,没有深入理解过其原理,这是很危险...

3227
来自专栏极客慕白的成长之路

jQuery深入——动画、常用工具、JSON、Ajax

4、停止动画 - stop([stopAll [, goToEnd]]) stopAll 布尔值,规定是否停止被选元素的所有加入队列的动画。默认是 false。...

1221
来自专栏扎心了老铁

zookeeper curator选主(Leader)

在分布式系统设计中,选主是一个常见的场景。选主是一个这样的过程,通过选主,主节点被选择出来控制其他节点或者是分配任务。 选主算法要满足的几个特征: 1)各个节点...

6146
来自专栏前端杂货铺

WebWorker的importScripts方法

简述   在《JavaScript高级程序设计(第三版)》中,提到WebWorker的importScripts方法是异步执行的,然而在 另一本书《Javasc...

2846
来自专栏林冠宏的技术文章

java 线程 Thread 使用介绍,包含wait(),notifyAll() 等函数使用介绍

(原创,转载请说明出处!谢谢--https://cloud.tencent.com/developer/user/1148436/activities)  此文...

1927
来自专栏DT乱“码”

jQuery封装的AJAX使用

jQuery 中的 Ajax jQuery为我们提供了更强大的Ajax封装 $.ajax({}) 可配置方式发起Ajax请求 $.get() 以GET方式发起A...

2566

扫码关注云+社区