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。其他线程状态,感兴趣的话,可以自行输出验证一下线程状态间的转换。

 

posted @ 2021-07-04 18:00  范丰平  Views(96)  Comments(0Edit  收藏  举报