五种:

线程在一定条件下,状态会发生变化。线程一共有以下几种状态:

1、新建状态(New):新创建了一个线程对象。

2、就绪状态(Runnable):线程对象创建后,其他线程调用了该对象的start()方法。该状态的线程位于“可运行线程池”中,变得可运行,只等待获取CPU的使用权,

即在就绪状态的进程除CPU之外,其它的运行所需资源都已全部获得。

3、运行状态(Running):就绪状态的线程获取了CPU,执行程序代码。

4、阻塞状态(Blocked):阻塞状态是线程因为某种原因放弃CPU使用权,暂时停止运行。直到线程进入就绪状态,才有机会转到运行状态。

阻塞的情况分三种:

①.等待阻塞:运行的线程执行wait()方法,该线程会释放占用的所有资源,JVM会把该线程放入“等待池”中。进入这个状态后,是不能自动唤醒的,

必须依靠其他线程调用notify()或notifyAll()方法才能被唤醒,

②.同步阻塞:运行的线程在获取对象的同步锁时,若该同步锁被别的线程占用,则JVM会把该线程放入“锁池”中。

③.其他阻塞:运行的线程执行sleep()或join()方法,或者发出了I/O请求时,JVM会把该线程置为阻塞状态。当sleep()状态超时、join()等待线程终止或者超时,

或者I/O处理完毕时,线程重新转入就绪状态。

5、死亡状态(Dead):线程执行完了或者因异常退出了run()方法,该线程结束生命周期。

线程变化的状态转换图如下:

PS:拿到对象的锁标记,即为获得了对该对象(临界区)的使用权限。即该线程获得了运行所需的资源,进入“就绪状态”,只需获得CPU,就可以运行。

因为当调用wait()后,线程会释放掉它所占有的“锁标志”,所以线程只有在此获取资源才能进入就绪状态。

下面作下解释:

①.线程的实现有两种方式,一是继承Thread类,二是实现Runnable接口,但不管怎样,  当我们new了这个对象后,线程就进入了初始状态;

②.当该对象调用了start()方法,就进入就绪状态;

③.进入就绪后,当该对象被操作系统选中,获得CPU时间片就会进入运行状态;

④.进入运行状态后情况就比较复杂;

(1)run()方法或main()方法结束后,线程就进入终止状态;

(2)当线程调用了自身的sleep()方法或其他线程的join()方法,进程让出CPU,然后就会进入阻塞状态(该状态既停止当前线程,但并不释放所占有的资源,

即调用sleep()函数后,线程不会释放它的“锁标志”。)。当sleep()结束或join()结束后,该线程进入可运行状态,继续等待OS分配CPU时间片;

典型地,sleep()被用在等待某个资源就绪的情形;测试发现条件不满足后,让线程阻塞一段时间后重新测试,直到条件满足为止。

(3)线程调用了yield()方法,意思是放弃当前获得的CPU时间片,回到就绪状态,这时与其他进程处于同等竞争状态,OS有可能会接着又让这个进程进入运行状态;

调用 yield() 的效果等价于调度程序认为该线程已执行了足够的时间片从而需要转到另一个线程。yield()只是使当前线程重新回到可执行状态,

所以执行yield()的线程有可能在进入到可执行状态后马上又被执行。

(4)当线程刚进入可运行状态(注意,还没运行),发现将要调用的资源被synchroniza(同步),获取不到锁标记,将会立即进入锁池状态,等待获取锁标记

(这时的锁池里也许已经有了其他线程在等待获取锁标记,这时它们处于队列状态,既先到先得),一旦线程获得锁标记后,就转入就绪状态,等待OS分配CPU时间片。

(5)suspend() 和 resume()方法:两个方法配套使用,suspend()使得线程进入阻塞状态,并且不会自动恢复,必须其对应的resume()被调用,才能使得线程重新进入可执行状态。

典型地,suspend()和 resume() 被用在等待另一个线程产生的结果的情形:测试发现结果还没有产生后,让线程阻塞,另一个线程产生了结果后,调用resume()使其恢复。

(6)wait()和 notify() 方法:当线程调用wait()方法后会进入等待队列(进入这个状态会释放所占有的所有资源,与阻塞状态不同),进入这个状态后,是不能自动唤醒的,

必须依靠其他线程调用notify()或notifyAll()方法才能被唤醒(由于notify()只是唤醒一个线程,但我们由不能确定具体唤醒的是哪一个线程,也许我们需要唤醒的线程不能够被唤醒,

因此在实际使用时,一般都用notifyAll()方法,唤醒有所线程),线程被唤醒后会进入锁池,等待获取锁标记。

wait() 使得线程进入阻塞状态,它有两种形式:

一种允许指定以ms为单位的时间作为参数,另一种没有参数。前者当对应的notify()被调用或超出指定时间时线程重新进入可执行状态即就绪状态,后者则必须对应的notify()被调用。

当调用wait()后,线程会释放掉它所占有的“锁标志”,从而使线程所在对象中的其它synchronized数据可被别的线程使用。

waite()和notify()因为会对对象的“锁标志”进行操作,所以它们必须在synchronized函数或synchronizedblock中进行调用。

如果在non-synchronized函数或non-synchronizedblock中进行调用,虽然能编译通过,但在运行时会发生IllegalMonitorStateException的异常。

六种:

NEW:线程被创建出来了,但是还没有start()。

RUNNABLE:可运行状态,这个状态比较特殊,我在图中把这个状态拆分成了两部分:一部分是READY,顾名思义是准备状态,另一部分是RUNNING,即运行状态。

准备状态:只能说明你有资格运行,单只要调度程序没有调度到你,你就永远是准备状态。从图中可以看出,好几个状态都能切换到准备状态,至于切换的方法,我在下文详细给大家整理出来介绍。

运行状态:线程调度程序从可运行池中选择一个线程作为当前线程时线程所处的状态。这也是线程进入运行状态的唯一一种方式。说白了,就是线程跑起来了。

BLOCKED:阻塞状态是线程阻塞在进入synchronized关键字修饰的方法或代码块(获取锁)时的状态。

WAITING:等待状态的线程不会被分配 CPU 执行时间,它们要等待被显式地唤醒,否则会处于无限期等待的状态。

TIMED_WAITING:超时等待状态的线程不会被分配 CPU 执行时间,不过无须无限期等待被其他线程显示地唤醒,在达到一定时间后它们会自动唤醒。这是和上面的 WAITING 状态的区别。

TERMINATED:终止状态,顾名思义,线程执行结束了。

为什么会有五种和六种的说法呢,其实,实际上,两种都算是对的,只不过,线程有六种状态更贴近官方的说法,更为合适一些。以上仅是个人看法,如有不同意见,欢迎评论区交流沟通

线程状态是五种对?还是六种对?相关推荐

  1. 线程及线程池的五种状态

    线程的5种状态 线程可以有如下5种状态:New .Runnable .Running .Blocked .Dead 状态之间的转换如图: 1.New (新创建) 当用new操作符创建一个线程时,如ne ...

  2. 线程池的五种状态及创建线程池的几种方式

    上篇<Java线程的6种状态详解及创建线程的4种方式> 前言:我们都知道,线程是稀有资源,系统频繁创建会很大程度上影响服务器的使用效率,如果不加以限制,很容易就会把服务器资源耗尽.所以,我 ...

  3. Java并发编程一线程池的五种状态

    推荐:Java并发编程汇总 Java并发编程一线程池的五种状态 原文地址 Java多线程线程池(4)–线程池的五种状态 正文 线程池的5种状态:Running.ShutDown.Stop.Tidyin ...

  4. 理解Java线程状态(6种,6种,6种)

    什么是线程 线程具有许多传统进程所具有的特征,故又称为轻型进程(Light-Weight Process)或进程元:而把传统的进程称为重型进程(Heavy-Weight Process),它相当于只有 ...

  5. 关于线程池的五种实现方式,七大参数,四种拒绝策略

    一.池化技术之线程池 实现线程池视频讲解,附源码:「链接」 什么是池化技术?简单来说就是优化资源的使用,我准备好了一些资源,有人要用就到我这里拿,用完了就还给我.而一个比较重要的的实现就是线程池.那么 ...

  6. 关于线程池的五种实现方式,中软国际Java机试

    在这里,还有创建一个只有单个线程的可以定时执行线程池(Executors.newSingleThreadScheduledExecutor())这些都是上面的线程池扩展开来了,不详细介绍了. 3 介绍 ...

  7. JAVA中创建线程池的五种方法及比较

    之前写过JAVA中创建线程的三种方法及比较.这次来说说线程池. JAVA中创建线程池主要有两类方法,一类是通过Executors工厂类提供的方法,该类提供了4种不同的线程池可供使用.另一类是通过Thr ...

  8. 线程池的五种状态详解

    线程池的5种状态:Running.ShutDown.Stop.Tidying.Terminated. 概述 最好的学习方式就是看源码,众所周知,创建线程池肯定会使用到ThreadPoolExecuto ...

  9. Java线程池--线程池的五种状态

    线程池的5种状态:Running.ShutDown.Stop.Tidying.Terminated. 线程池各个状态切换框架图: 1.RUNNING (1) 状态说明:线程池处在RUNNING状态时, ...

最新文章

  1. 在函数调用中,星号运算符是什么意思? [重复]
  2. 项目: 用函数实现反弹球消砖块
  3. VTK:vtkBooleanOperationPolyDataFilter用法实战
  4. 利用链表实现可合并堆(算法导论第三版思考题10-2)
  5. 欢乐ssl暑假赛【2019.8.6】
  6. 2019全球编程语言高薪排行榜登场;余承东正式宣布华为IFA2019 或发布麒麟990;OPPO、vivo和小米成立互传联盟…...
  7. Ubuntu系统挂载U盘
  8. 学校实训 电力巡检系统管理平台
  9. python实现MD5加密工具
  10. 情人节程序员用HTML网页表白【新婚快乐】 HTML5七夕情人节表白网页源码 HTML+CSS+JavaScript
  11. 手机ROM,RAM作假显示
  12. 太合音乐领千千音乐突围:在线音乐铜墙铁壁难闯
  13. 由浅入深玩转华为WLAN—11 安全认证配置(4)AC内置Portal认证(网页认证)
  14. android 6g 有必要吗,Android手机: 6G和8G运行内存之间有多大差异?网民: 做这些事有区别...
  15. GitBook建立本地Book及导入别人Book
  16. 读懂 x86 架构 Linux 系统虚拟化,这文不容错过
  17. 开源的意义是什么?盘点当前五大优质开源项目
  18. CMakeCMakeList.txt
  19. matlab星三角变压器,变压器星三角接法_主变低压侧三角接法
  20. 上门按摩预约小程序APP软件系统部署讲解

热门文章

  1. 使用npm下载包,报错 error An unexpected error occurred: “EPERM: operation not permitted
  2. 【算法】Sunday算法(模式匹配)
  3. php取word表格一行内容,如何提取出word表格中的内容 值得一看
  4. 图像显著性论文(六)—Saliency Filters Contrast Based Filtering for Salient Region Detection
  5. Spring 教程(一)
  6. React.createElement的理解使用
  7. anacoda里面安装包显示失败_Revit问题-运行库安装错误导致软件安装失败
  8. 业务逻辑漏洞之水平越权和垂直越权
  9. 4.基于NIO的群聊系统
  10. php 调用 C++