Java学习-081-多线程14:线程状态示例
Java 线程的 6 种状态:
- 初始(NEW):新创建了一个线程对象,但还没有调用 start() 方法。
- 运行(RUNNABLE):调用线程的 start() 方法,线程进入可运行线程池中,线程就绪(READY),等待被 CPU线程调度执行;当获取 CPU 时间片开始执行后,线程运行中(RUNNING)。通常,Java 线程中将就绪(READY)和运行中(RUNNING)两种状态统称为运行(RUNNABLE)。
- 阻塞(BLOCKED):表示线程阻塞于锁,是指线程因为某种原因失去了 CPU 使用权(让出 CPU timeslice),暂时停止运行。直到线程进入可运行(RUNNABLE)状态,才有 机会再次获得 CPU timeslice 转到运行(RUNNING)状态。导致线程阻塞的情况主要有三种:
- 等待阻塞 :运行(RUNNING)的线程执行 o.wait() 方法,JVM 会把该线程放入等待队列(WAITING QUEUE)中
- 同步阻塞 :运行(RUNNING)的线程在获取对象的同步锁时,若该同步锁被其他线程占用,则 JVM 会把该线程放入锁池(lock pool)中
- 其他阻塞 : 运行(RUNNING)的线程执行 Thread.sleep(long ms)、otherThread.join() 方法、发出了 I/O 请求时,JVM 会把该线程置为阻塞状态。此时不会主动释放锁,当 sleep 完成、join 线程终止/超时、I/O 处理完成时,才会释放锁,进入可运行状态(RUNNABLE)
- 等待(WAITING):进入该状态的线程需要等待其他线程做出一些特定动作(通知或中断)。
- 超时等待(TIMED_WAITING):线程执行了 Thread.sleep(ms) 后进入该状态,该状态相较于 WAITING 可在指定的休眠时间结束后自行返回进入运行状态。
- 终止(TERMINATED):表示该线程已经执行完毕。当线程 run() || interrupt() || main() 方法执行结束,或者发生异常退出了 run() || main() 方法,则线程生命周期结束。
通过一段代码简单演示一下线程状态,源代码如下所示:
package com.fanfengping.demo; import lombok.extern.slf4j.Slf4j; import java.io.*; @Slf4j public class Demo10RunnableInterrupt implements Runnable { @Override public synchronized void run() { Thread thread = Thread.currentThread(); try { log.info("t1 >> {} 开始运行", thread.getName()); log.info("t2 >> {} 运行状态:{},是否存活:{},是否被中断:{}", thread.getName(), thread.getState().name(), thread.isAlive(), thread.isInterrupted()); log.info("t3 >> {} 开始休眠", thread.getName()); Thread.sleep(3000); log.info("t4 >> {} 结束休眠", thread.getName()); log.info("t5 >> {} 开始写文件", thread.getName()); for (int i = 0; i < 800; i++) { File file=new File("E:/office-new/personal/multi-thread-demo/src/main/resources/files/test-" + i + ".log"); if(!file.exists()) file.createNewFile(); FileOutputStream out = new FileOutputStream(file,true); for(int j=0;j<10000;j++) { StringBuffer sb = new StringBuffer(); sb.append("这是第"+i+"行:前面介绍的各种方法都不关用,为什么总是奇怪的问题 "); out.write(sb.toString().getBytes("utf-8")); } out.close(); } log.info("t6 >> {} 结束写文件", thread.getName()); log.info("t7 >> {} 开始休眠", thread.getName()); Thread.sleep(5000); log.info("t8 >> {} 结束休眠", thread.getName()); } catch (InterruptedException | UnsupportedEncodingException e) { log.error("t9 >> " + thread.getName() + " 被中断", e); } catch (FileNotFoundException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } } public static void main(String[] args) { try { Demo10RunnableInterrupt demo10RunnableInterrupt = new Demo10RunnableInterrupt(); Thread threadInterrupt = new Thread(demo10RunnableInterrupt, "Interrupt_demo"); log.info("1 >> {} 运行状态:{},是否存活:{},是否被中断:{}", threadInterrupt.getName(), threadInterrupt.getState().name(), threadInterrupt.isAlive(), threadInterrupt.isInterrupted()); log.info("2 >> {} 启动线程", threadInterrupt.getName()); threadInterrupt.start(); log.info("3 >> 主线程休眠 1 秒"); Thread.sleep(1000); log.info("4 >> {} 运行状态:{},是否存活:{},是否被中断:{}", threadInterrupt.getName(), threadInterrupt.getState().name(), threadInterrupt.isAlive(), threadInterrupt.isInterrupted()); log.info("5 >> 主线程休眠 7 秒"); Thread.sleep(7000); log.info("6 >> {} 中断线程", threadInterrupt.getName()); threadInterrupt.interrupt(); log.info("7 >> 主线程休眠 1 秒"); Thread.sleep(1000); log.info("8 >> {} 运行状态:{},是否存活:{},是否被中断:{}", threadInterrupt.getName(), threadInterrupt.getState().name(), threadInterrupt.isAlive(), threadInterrupt.isInterrupted()); log.info("9 >> 主线程休眠 18 秒"); Thread.sleep(18000); log.info("10 >> {} 运行状态:{},是否存活:{},是否被中断:{}", threadInterrupt.getName(), threadInterrupt.getState().name(), threadInterrupt.isAlive(), threadInterrupt.isInterrupted()); log.info("11 >> 主线程休眠 40 秒"); Thread.sleep(40000); log.info("12 >> {} 运行状态:{},是否存活:{},是否被中断:{}", threadInterrupt.getName(), threadInterrupt.getState().name(), threadInterrupt.isAlive(), threadInterrupt.isInterrupted()); } catch (InterruptedException e) { e.printStackTrace(); } } }
执行后,控制台输出如下所示:
[main] INFO com.fanfengping.demo.Demo10RunnableInterrupt - 1 >> Interrupt_demo 运行状态:NEW,是否存活:false,是否被中断:false [main] INFO com.fanfengping.demo.Demo10RunnableInterrupt - 2 >> Interrupt_demo 启动线程 [main] INFO com.fanfengping.demo.Demo10RunnableInterrupt - 3 >> 主线程休眠 1 秒 [Interrupt_demo] INFO com.fanfengping.demo.Demo10RunnableInterrupt - t1 >> Interrupt_demo 开始运行 [Interrupt_demo] INFO com.fanfengping.demo.Demo10RunnableInterrupt - t2 >> Interrupt_demo 运行状态:RUNNABLE,是否存活:true,是否被中断:false [Interrupt_demo] INFO com.fanfengping.demo.Demo10RunnableInterrupt - t3 >> Interrupt_demo 开始休眠 [main] INFO com.fanfengping.demo.Demo10RunnableInterrupt - 4 >> Interrupt_demo 运行状态:TIMED_WAITING,是否存活:true,是否被中断:false [main] INFO com.fanfengping.demo.Demo10RunnableInterrupt - 5 >> 主线程休眠 7 秒 [Interrupt_demo] INFO com.fanfengping.demo.Demo10RunnableInterrupt - t4 >> Interrupt_demo 结束休眠 [Interrupt_demo] INFO com.fanfengping.demo.Demo10RunnableInterrupt - t5 >> Interrupt_demo 开始写文件 [main] INFO com.fanfengping.demo.Demo10RunnableInterrupt - 6 >> Interrupt_demo 中断线程 [main] INFO com.fanfengping.demo.Demo10RunnableInterrupt - 7 >> 主线程休眠 1 秒 [main] INFO com.fanfengping.demo.Demo10RunnableInterrupt - 8 >> Interrupt_demo 运行状态:RUNNABLE,是否存活:true,是否被中断:true [main] INFO com.fanfengping.demo.Demo10RunnableInterrupt - 9 >> 主线程休眠 18 秒 [main] INFO com.fanfengping.demo.Demo10RunnableInterrupt - 10 >> Interrupt_demo 运行状态:RUNNABLE,是否存活:true,是否被中断:true [main] INFO com.fanfengping.demo.Demo10RunnableInterrupt - 11 >> 主线程休眠 40 秒 [Interrupt_demo] INFO com.fanfengping.demo.Demo10RunnableInterrupt - t6 >> Interrupt_demo 结束写文件 [Interrupt_demo] INFO com.fanfengping.demo.Demo10RunnableInterrupt - t7 >> Interrupt_demo 开始休眠 [Interrupt_demo] ERROR com.fanfengping.demo.Demo10RunnableInterrupt - t9 >> Interrupt_demo 被中断 java.lang.InterruptedException: sleep interrupted at java.lang.Thread.sleep(Native Method) at com.fanfengping.demo.Demo10RunnableInterrupt.run(Demo10RunnableInterrupt.java:37) at java.lang.Thread.run(Thread.java:748) [main] INFO com.fanfengping.demo.Demo10RunnableInterrupt - 12 >> Interrupt_demo 运行状态:TERMINATED,是否存活:false,是否被中断:false
由上述源码输出日志可以看出,线程总计经历了四个状态 NEW、RUNNABLE、TIMED_WAITING、TERMINATED。其他线程状态,感兴趣的话,可以自行输出验证一下线程状态间的转换。
欢迎 【 留言 || 关注 || 打赏 】 。您的每一份心意都是对我的鼓励和支持!非常感谢!欢迎互加,相互交流学习!
作者:范丰平,本文链接:https://www.cnblogs.com/fengpingfan/p/14719241.html
Copyright @范丰平 版权所有,如需转载请标明本文原始链接出处,严禁商业用途! 我的个人博客链接地址:http://www.cnblogs.com/fengpingfan