线程的状态 骑猪看日落 2023-10-10 15:37 5阅读 0赞 ## ![30c62856180b41619343cf2eabf4bcf3.png][] ## **目录** 1.线程的状态 2.线程状态的转换 3.多线程的意义 -------------------- ## 1.线程的状态 ## 线程是操作系统调度的基本单位,线程的状态是一个枚举类型 通过遍历可以打印得到线程的状态的名称 public class ThreadDemo12 { public static void main(String[] args) { for (Thread.State state : Thread.State.values() ) { System.out.println(state); } } } ![bf43cebdc0f0460dbd6c0be6952e0379.png][] Java中对线程的状态做了细化,一共有六个状态 1.1 NEW 仅仅只创建了Three对象,还没调用start方法,内核没有创建对应的PCB 1.2 TERMINATED 表示内核中的PCB已经执行完了,但是Thread对象还在 1.3 RUNNABLE 可运行的,包含正在CPU上执行的,或者正在就绪队列中,随时可以取CPU上执行的 1.4 WAITING 表示线程阻塞 1.5 TIMED\_WAITING 表示线程阻塞 1.6 BLOCKED 表示线程阻塞 后三个状态是不同原因的阻塞 ## 2.线程状态的转换 ## 线程状态的大致转换如图 ![99ca827e2a5943b3986006d83d62e7f6.png][]主线是由NEW->RUNNALBE->TERMINATED,从线程创建到线程执行再到线程结束 支线就是在三种不同的操作下引起的阻塞状态,是在RUNNABLE状态时进行的 下面结合代码可以直观地看到线程的状态 public class ThreadDemo12 { public static void main(String[] args) { Thread t = new Thread(()->{ for (int i = 0; i < 10000000; i++) { } }); System.out.println("t.start之前:"+t.getState()); t.start(); try { t.join(); } catch (InterruptedException e) { throw new RuntimeException(e); } System.out.println("t.start之后:"+t.getState()); } } ![915e6c0e8b0a4fb598478faa560f09c4.png][] TERMINATED的存在是因为内核线程释放的时候,不能保证线程对象也立即释放,因此存在线程释放后线程对象还存在,生命周期是不一致的,所以需要通过一个特定的状态来将线程对象标识成无效,不能再使用,也不能重新start,一个线程只能创建一次PCB 线程结束后,无法再利用多线程了,但是线程对象还存在,还可以用线程对象调用一些方法和属性 接下来查看RUNNABLE状态: 这里能看到RUNNABLE状态是因为run方法中没有sleep之类的方法 ![e5eb392959bb472eb4ce439c6ad2a766.png][] 如果run方法中有sleep,那么线程的状态就是RUNNABLE或者TIMED\_WAITING,取决于线程运行到哪个环节了 public static void main(String[] args) { Thread t = new Thread(()->{ for (int i = 0; i < 100; i++) { try { Thread.sleep(10); } catch (InterruptedException e) { throw new RuntimeException(e); } } }); System.out.println("t.start之前:"+t.getState()); t.start(); for (int i = 0; i < 1000; i++) { System.out.println("线程执行中的状态:"+t.getState()); } try { t.join(); } catch (InterruptedException e) { throw new RuntimeException(e); } System.out.println("t.start之后:"+t.getState()); } run方法中加sleep后,循环打印start后线程状态的结果 ![9af1e01ac5bc4cdc946fca2c9b978816.png][] 多次获取后我们看到线程状态从RUNNABLE转换到TIMED\_WAITING,当前获取到的状态是什么,完全取决于操作系统的调度,获取状态的瞬间,线程对象是在执行还是在休眠!! 还有两种阻塞I(WAITING/BLOCKED)状态后续写到对应方法再进行叙述 ## 3.多线程的意义 ## 通过下面代码感受多线程和单线程之间执行速度的差别 程序分为cpu密集和IO密集,cpu密集包含大量的加减乘除运算,IO密集涉及到读写文件,读写控制台,读写网络,这里我们通过cpu密集的程序来感受多线程的特点 假设当前有两个变量需要把他们各自自增1000W次,分别通过单线程和多线程实现 可以通过一个线程,先对a自增,后对b自增 也可以多线程,分别对ab自增 先看单线程执行时间 public class ThreadDemo13 { public static void main(String[] args) { serial(); } public static void serial(){ long beg = System.currentTimeMillis(); long a = 0; for (long i = 0; i < 100_000_0000L; i++) { a++; } long b = 0; for (long i = 0; i < 100_000_0000L; i++) { b++; } long end = System.currentTimeMillis(); System.out.println("执行时间: "+(end-beg)+" ms"); } } 单线程多次运行后,执行的时间 ![fbbfdb76f0d44cfd9862f4b3546ea136.png][] public static void concurrency(){ Thread t1 = new Thread(()->{ long a = 0; for (long i = 0; i < 100_0000_0000L; i++) { a++; } }); Thread t2 = new Thread(()->{ long b = 0; for (long i = 0; i < 100_0000_0000L; i++) { b++; } }); long beg = System.currentTimeMillis(); t1.start(); t2.start(); try { t1.join(); t2.join(); } catch (InterruptedException e) { throw new RuntimeException(e); } long end = System.currentTimeMillis(); System.out.println("并发执行耗时:"+(end-beg)+" ms"); } > 注意:如果在调用两个start后没有加join方法等待t1t2线程执行结束,那么执行时间就会使0ms > > 因为当主线和t1t2线程并发执行时,谁先执行是不确定的,如果刚调完t1t2,main线程就继续执行,那么打印的时间就是0,因此要先让两个线程执行结束,再继续进行主线程 > > 在主线程调用join方法只能保证主线程是最后结束的,另外的两个线程执行的顺序和谁先结束谁后结束是不确定的 并发执行后,多次执行的时间![7724f5b9cbd84cb08ab7fb35e8b83719.png][] 多线程执行的时间相比于串行执行时间,明显缩短了,为什么没有缩短一半呢? > 因为保证不了并行执行!在执行过程中会经历很多次的调度,过程中可能是并发执行(同一时间间隔上在一个核心上执行)或者并行执行(在多个核心上同时执行) > > 线程调度自身也有时间消耗,因此很难让时间正好是串行调度的一半,即使是这样,多线程执行任然有很大的意义 多线程在cpu密集型的任务中,有非常大的作用,可以充分利用cpu的多核资源,从而加快程序的运行效率 也不是多线程就一定能提高效率,要看是否是多核,二是当前核心是否空闲,如果cpu当前已经满载了,使用多线程也不能提高效率 在IO密集型任务中.经常看到"程序未响应".比如启动一个比较大的游戏的时候,要加载大量的数据文件,涉及到大量的读硬盘操作,阻塞了界面响应,多线程也是能起到一定的改善作用(让一个线程负责IO,另一个线程来响应用户的操作) [30c62856180b41619343cf2eabf4bcf3.png]: https://img-blog.csdnimg.cn/30c62856180b41619343cf2eabf4bcf3.png [bf43cebdc0f0460dbd6c0be6952e0379.png]: https://img-blog.csdnimg.cn/bf43cebdc0f0460dbd6c0be6952e0379.png [99ca827e2a5943b3986006d83d62e7f6.png]: https://img-blog.csdnimg.cn/99ca827e2a5943b3986006d83d62e7f6.png [915e6c0e8b0a4fb598478faa560f09c4.png]: https://img-blog.csdnimg.cn/915e6c0e8b0a4fb598478faa560f09c4.png [e5eb392959bb472eb4ce439c6ad2a766.png]: https://img-blog.csdnimg.cn/e5eb392959bb472eb4ce439c6ad2a766.png [9af1e01ac5bc4cdc946fca2c9b978816.png]: https://img-blog.csdnimg.cn/9af1e01ac5bc4cdc946fca2c9b978816.png [fbbfdb76f0d44cfd9862f4b3546ea136.png]: https://img-blog.csdnimg.cn/fbbfdb76f0d44cfd9862f4b3546ea136.png [7724f5b9cbd84cb08ab7fb35e8b83719.png]: https://img-blog.csdnimg.cn/7724f5b9cbd84cb08ab7fb35e8b83719.png
相关 线程的状态 在Java中线程共分为6中状态: 1. NEW:创建好一个Java的Thread对象,并安排好了任务,没有调用start()方法,和PCB没有关系 1. RUNNABL 缺乏、安全感/ 2024年03月30日 14:38/ 0 赞/ 75 阅读
相关 线程状态和线程池状态 线程状态 有六种状态; 新创建(NEW) 可运行(Runnable) 锁阻塞(Blocked) 无线等待(Waiting) 计时等待(Timed Wa 桃扇骨/ 2023年10月06日 14:08/ 0 赞/ 43 阅读
相关 线程的状态 ![在这里插入图片描述][2d280b0176ba4be2ae9f37daba7f7c5d.gif_pic_center] 文章目录 一、线程的所有状态 二 ﹏ヽ暗。殇╰゛Y/ 2023年09月27日 13:09/ 0 赞/ 129 阅读
相关 线程的状态 我百度了一下,有说三种,有说四种,有说五种,有说六种,还有说七种。下边列出六种的说法,六种见的比较多。 这是线程的六种状态 1. 初始(NEW):新创建了一个线程对象, 墨蓝/ 2023年06月07日 05:37/ 0 赞/ 26 阅读
相关 线程的状态 线程的状态 在正式学习Thread类中的具体方法之前,我们先来了解一下线程有哪些状态,这个将会有助于后面对Thread类中的方法的理解。 线程从创建到最终的消亡,要 Dear 丶/ 2022年09月24日 14:22/ 0 赞/ 198 阅读
相关 线程的状态 要想实现多线程,必须在主线程中创建新的线程对象。任何线程一般具有5种状态, 即 创建、就绪、运行、阻塞、终止。线程状态的转移与方法之间的关系如图所示 ![这里写图片描述][ 心已赠人/ 2022年07月21日 02:49/ 0 赞/ 229 阅读
相关 线程的状态 线程对象在不同的运行时期有不同的状态,状态信息就存在于State枚举类中, \ public static enum Thread.State extends En 秒速五厘米/ 2022年06月08日 00:46/ 0 赞/ 224 阅读
相关 线程的状态 Thread源码里定义了6种状态,如下: \ A thread state. A thread can be in one of the follo 川长思鸟来/ 2022年02月15日 13:47/ 0 赞/ 272 阅读
相关 线程的状态 线程共有六种状态 ![在这里插入图片描述][watermark_type_ZmFuZ3poZW5naGVpdGk_shadow_10_text_aHR0cHM6Ly9ibG9 妖狐艹你老母/ 2021年12月19日 00:21/ 0 赞/ 379 阅读
相关 线程的状态 RUNNABLE这个名字很具有欺骗性,很容易让人误以为处于这个状态的线程正在运行。事实上,这个状态只是表示,线程是可运行的。我们已经无数次提到过,一个单核CPU在同一时刻... 朱雀/ 2020年05月12日 15:57/ 0 赞/ 910 阅读
还没有评论,来说两句吧...