zoukankan      html  css  js  c++  java
  • Java学习-081-多线程14:线程状态示例

    Java 线程的 6 种状态:

    1. 初始(NEW):新创建了一个线程对象,但还没有调用 start() 方法。
    2. 运行(RUNNABLE):调用线程的 start() 方法,线程进入可运行线程池中,线程就绪(READY),等待被 CPU线程调度执行;当获取 CPU 时间片开始执行后,线程运行中(RUNNING)。通常,Java 线程中将就绪(READY)和运行中(RUNNING)两种状态统称为运行(RUNNABLE)。
    3. 阻塞(BLOCKED):表示线程阻塞于锁,是指线程因为某种原因失去了 CPU 使用权(让出 CPU timeslice),暂时停止运行。直到线程进入可运行(RUNNABLE)状态,才有 机会再次获得 CPU timeslice 转到运行(RUNNING)状态。导致线程阻塞的情况主要有三种:
      1. 等待阻塞  :运行(RUNNING)的线程执行 o.wait() 方法,JVM 会把该线程放入等待队列(WAITING QUEUE)中
      2. 同步阻塞  :运行(RUNNING)的线程在获取对象的同步锁时,若该同步锁被其他线程占用,则 JVM 会把该线程放入锁池(lock pool)中
      3. 其他阻塞  : 运行(RUNNING)的线程执行 Thread.sleep(long ms)、otherThread.join() 方法、发出了 I/O 请求时,JVM 会把该线程置为阻塞状态。此时不会主动释放锁,当 sleep 完成、join 线程终止/超时、I/O 处理完成时,才会释放锁,进入可运行状态(RUNNABLE)
    4. 等待(WAITING):进入该状态的线程需要等待其他线程做出一些特定动作(通知或中断)。
    5. 超时等待(TIMED_WAITING):线程执行了 Thread.sleep(ms) 后进入该状态,该状态相较于 WAITING 可在指定的休眠时间结束后自行返回进入运行状态。
    6. 终止(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。其他线程状态,感兴趣的话,可以自行输出验证一下线程状态间的转换。

    我本渺小,但山峰,我一次次绝顶!


    PS:若有错误,敬请告知,不胜感激!
    Copyright @范丰平 版权所有,如需转载请标明本文原始链接出处,严禁商业用途! 我的个人博客链接地址:http://www.cnblogs.com/fengpingfan
  • 相关阅读:
    最长上升序列,首尾连接
    带权并查集&&并查集
    开发者的小天地-1
    Binary Tree Maximum Path Sum
    Linked List Cycle II
    动归熟手题单
    java 正则表达式-忽略大小写与多行匹配
    KO之tab栏切换
    Vue中通过属性绑定为元素绑定style
    Vue中通过属性绑定为元素设置class
  • 原文地址:https://www.cnblogs.com/fengpingfan/p/14719241.html
Copyright © 2011-2022 走看看