Java线程生命周期及转换过程

目录
  • Java 线程生命周期
  • 生命周期转换
    • 1.从 NEW 到 RUNNABLE
    • 2.从 RUNNABLE 到 BLOCKED
    • 3.从 RUNNABLE 到 WAITTING
    • 4.从 RUNNABLE 到 TIMED_WATTING
    • 5.RUNNABLE 到 TERMINATED
  • 总结

前言:

线程的生命周期指的是线程从创建到销毁的整个过程,通常情况下线程的生命周期有以下 5 种:

  • 初始状态
  • 可运行状态
  • 运行状态
  • 休眠状态
  • 终止状态

它们的状态转换如下图所示: 

Java 线程生命周期

Java 线程的生命周期和上面说的生命周期是不同的,它有以下 6 种状态:

  • NEW(初始化状态)
  • RUNNABLE(可运行/运行状态)
  • BLOCKED(阻塞状态)
  • WAITING(无时限等待状态)
  • TIMED_WAITING(有时限等待状态)
  • TERMINATED(终止状态)

我们可以在 Thread 的源码中可以找到这 6 种状态,如下所示: 

 当然你也可以使用 Java 代码,来打印所有的线程状态,如下代码所示:

for (Thread.State value : Thread.State.values()) {
    System.out.println(value);
}

以上程序的执行结果如下图所示: 

生命周期转换

接下来我们聊聊 Java 线程生命周期的转换过程。

1.从 NEW 到 RUNNABLE

当我们创建一个线程的时候,也就是 new Thread 的时候,此时线程是 NEW 状态,如下代码所示:

// 创建线程
Thread thread = new Thread(new Runnable() {
    @Override
    public void run() {
        // ...
    }
});
// 获取线程状态
Thread.State state = thread.getState();
System.out.println(state);

以上程序的执行结果如下图所示: 

然而调用了线程的 start 方法之后,线程的状态就从 NEW 变成了 RUNNABLE,

如下代码所示:

// 创建线程
Thread thread = new Thread(new Runnable() {
    @Override
    public void run() {
        // 获取到当前执行的线程
        Thread currThread = Thread.currentThread();
        // 获取线程状态
        Thread.State state = currThread.getState();
        // 打印线程状态
        System.out.println(state);
    }
});
thread.start();

以上程序的执行结果如下图所示: 

2.从 RUNNABLE 到 BLOCKED

当线程中的代码排队执行 synchronized 时,线程就会从 RUNNABLE 状态变为 BLOCKED 阻塞状态

如下代码所示:

// 创建线程
Thread thread = new Thread(new Runnable() {
    @Override
    public void run() {
        try {
            // 等待 100 毫秒
            Thread.sleep(100);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println("排队使用锁");
        synchronized (ThreadStates.class) {
        }
    }
});
thread.start();
// 让主线程先得到锁
synchronized (ThreadStates.class) {
    // 获取线程状态
    Thread.State state = thread.getState();
    // 打印线程状态
    System.out.println("首次获取线程状态:" + state);
    // 休眠 1s
    try {
        Thread.sleep(1000);
    } catch (InterruptedException e) {
        e.printStackTrace();
    }
    // 再次获取线程状态
    state = thread.getState();
    // 打印线程状态
    System.out.println("第二次获取线程状态:" + state);
}

以上程序的执行结果如下图所示: 

当线程获取到 synchronized 锁之后,就会从 BLOCKED 状态转变为 RUNNABLE 状态。

3.从 RUNNABLE 到 WAITTING

线程调用 wait() 方法之后,就会从 RUNNABLE 状态变为 WAITING 无时限等待状态,如下所示:

// 创建线程
Thread thread = new Thread(new Runnable() {
    @Override
    public void run() {
        synchronized (this) {
            try {
                // 线程休眠
                this.wait();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
});
// 启动线程
thread.start();
// 获取线程状态
Thread.State state = thread.getState();
// 打印线程状态
System.out.println("首次获取线程状态:" + state);
// 休眠 1s
try {
    Thread.sleep(1000);
} catch (InterruptedException e) {
    e.printStackTrace();
}
// 获取线程状态
state = thread.getState();
// 打印线程状态
System.out.println("第二次获取线程状态:" + state);

以上程序的执行结果如下图所示: 

当调用了 notify/notifyAll 方法之后,线程会从 WAITING 状态变成 RUNNABLE 状态,

如下代码所示:

Object lock = new Object();
// 创建线程
Thread thread = new Thread(new Runnable() {
    @Override
    public void run() {
        synchronized (lock) {
            try {
                // 线程休眠
                lock.wait();
                // 获取当前线程状态
                Thread.State state = Thread.currentThread().getState();
                // 打印线程状态
                System.out.println("获取线程状态:" + state);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
});
// 启动线程
thread.start();
// 获取线程状态
Thread.State state = thread.getState();
// 打印线程状态
System.out.println("首次获取线程状态:" + state);
// 休眠 1s
try {
    Thread.sleep(100);
} catch (InterruptedException e) {
    e.printStackTrace();
}
// 获取线程状态
state = thread.getState();
// 打印线程状态
System.out.println("第二次获取线程状态:" + state);

// 唤醒 thread 线程
synchronized (lock) {
    lock.notify();
}

以上程序的执行结果如下图所示: 

4.从 RUNNABLE 到 TIMED_WATTING

当调用带超时时间的等待方法时,如 sleep(xxx),线程会从 RUNNABLE 状态变成 TIMED_WAITING 有时限状态,

如下代码所示:

// 创建线程
Thread thread = new Thread(new Runnable() {
    @Override
    public void run() {
        try {
            Thread.sleep(1000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
});
// 启动线程
thread.start();
// 获取线程状态
Thread.State state = thread.getState();
// 打印线程状态
System.out.println("首次获取线程状态:" + state);
// 休眠 1s
try {
    Thread.sleep(100);
} catch (InterruptedException e) {
    e.printStackTrace();
}
// 获取线程状态
state = thread.getState();
// 打印线程状态
System.out.println("第二次获取线程状态:" + state);

以上程序的执行结果如下图所示: 

当超过了超时时间之后,线程就会从 TIMED_WAITING 状态变成 RUNNABLE 状态,

实现代码如下:

// 创建线程
Thread thread = new Thread(new Runnable() {
    @Override
    public void run() {
        try {
            Thread.sleep(1000);
            // 获取当前线程状态
            Thread.State state = Thread.currentThread().getState();
            // 打印线程状态
            System.out.println("获取线程状态:" + state);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
});
// 启动线程
thread.start();
// 获取线程状态
Thread.State state = thread.getState();
// 打印线程状态
System.out.println("首次获取线程状态:" + state);
// 休眠 1s
try {
    Thread.sleep(100);
} catch (InterruptedException e) {
    e.printStackTrace();
}
// 获取线程状态
state = thread.getState();
// 打印线程状态
System.out.println("第二次获取线程状态:" + state);

以上程序的执行结果如下图所示: 

5.RUNNABLE 到 TERMINATED

线程执行完之后,就会从 RUNNABLE 状态变成 TERMINATED 销毁状态,如下代码所示:

// 创建线程
Thread thread = new Thread(new Runnable() {
    @Override
    public void run() {
        // 获取当前线程状态
        Thread.State state = Thread.currentThread().getState();
        // 打印线程状态
        System.out.println("获取线程状态:" + state);
    }
});
// 启动线程
thread.start();
// 等待 100ms,待线程执行完
Thread.sleep(100);
// 获取线程状态
Thread.State state = thread.getState();
// 打印线程状态
System.out.println("线程状态:" + state);

以上程序的执行结果如下图所示: 

总结

Java 中线程的生命周期有 6 种:NEW(初始化状态)、RUNNABLE(可运行/运行状态)、BLOCKED(阻塞状态)、WAITING(无时限等待状态)、TIMED_WAITING(有时限等待状态)、TERMINATED(终止状态)。

线程生命周期的转换流程如下图所示: 

到此这篇关于Java线程生命周期及转换过程的文章就介绍到这了,更多相关Java线程内容请搜索我们以前的文章或继续浏览下面的相关文章希望大家以后多多支持我们!

(0)

相关推荐

  • java 线程的生命周期详解

    一个线程的生命周期: 新建状态: 使用 new 关键字和 Thread 类或其子类建立一个线程对象后,该线程对象就处于新建状态.它保持这个状态直到程序 start() 这个线程. 就绪状态: 当线程对象调用了start()方法之后,该线程就进入就绪状态.就绪状态的线程处于就绪队列中,要等待JVM里线程调度器的调度. 运行状态: 如果就绪状态的线程获取 CPU 资源,就可以执行 run(),此时线程便处于运行状态.处于运行状态的线程最为复杂,它可以变为阻塞状态.就绪状态和死亡状态. 阻塞状态: 如

  • 图解Java线程的生命周期

    在Java中,线程有5中不同状态,分别是:新建(New).就绪(Runable).运行(Running).阻塞(Blocked)和死亡(Dead).它们之间的转换图如下: 上图有一个例外,调用yield()方法可以让当前处于运行状态的线程转入就绪状态.如果要测试某线程是否已经死亡,可以使用isAlive()方法,该方法在线程处于就绪.运行.阻塞时放回true,新建和死亡时返回false.不要试图对一个已经死亡的线程调用start()方法而重新启动,死亡就是死亡和人一样,不可能再生.还有也不要对一

  • Java线程的生命周期的详解

    Java线程的生命周期的详解 对于多线程编程而言,理解线程的生命周期非常重要,本文就针对这一点进行讲解. 一.线程的状态 线程的存在有几种不同的状态,如下: New状态 Ready状态 Running状态 Dead状态 Non Runnable状态 1.New状态 New状态是线程已经被创建,但是还未开始运行的状态.此状态通过调用线程的start()方法可让线程运行. 2.Runnable状态 Runnable状态可称为准备运行状态,也可称为队列,此状态通过调用线程的start()方法可让线程运

  • 初步学习Java中线程的实现与生命周期

    线程的实现 在Java中通过run方法为线程指明要完成的任务,有两种技术来为线程提供run方法: 1.继承Thread类并重写它的run方法.之后创建这个子类的对象并调用start()方法. 2.通过定义实现Runnable接口的类进而实现run方法.这个类的对象在创建Thread的时候作为参数被传入,然后调用start()方法. Thread类是专门用来创建线程和对线程进行操作的类.当某个类继承了Thread类之后,该类就叫做一个线程类. 两种方法均需执行线程的start()方法为线程分配必须

  • Java 线程的生命周期完整实例分析

    本文实例讲述了Java 线程的生命周期.分享给大家供大家参考,具体如下: 一 代码 /** * @Title: ThreadStatus.java * @Description: TODO(演示线程的生命状态) */ import java.util.concurrent.locks.Lock; import java.util.concurrent.locks.ReentrantLock; import java.util.concurrent.TimeUnit; public class T

  • Java线程的生命周期命名与获取代码实现

    一.线程的生命周期 1.五种状态:新建状态.就绪状态.运行状态.阻塞状态.消亡状态 2.就绪状态的线程表示有权利去获取CPU的时间片,CPU时间片是执行权,当线程拿到CPU时间片之后就马上执行run方法,这个时候就代表进入了运行状态 二.线程的调度与控制 通常我们的计算机只有一个CPU,CPU在某一个时刻只能执行一条指令,线程只有得到CPU时间片,也就是使用权,才可以执行指令​.在单CPU的机器上线程不是并行运行的,只有个在多个CPU上线程才可以并行运行.Java虚拟机要负责线程的调度,取得CP

  • Java线程的生命周期和状态控制_动力节点Java学院整理

    一.线程的生命周期 线程状态转换图: 1.新建状态 用new关键字和Thread类或其子类建立一个线程对象后,该线程对象就处于新生状态.处于新生状态的线程有自己的内存空间,通过调用start方法进入就绪状态(runnable). 注意:不能对已经启动的线程再次调用start()方法,否则会出现Javalang.IllegalThreadStateException异常. 2.就绪状态 处于就绪状态的线程已经具备了运行条件,但还没有分配到CPU,处于线程就绪队列(尽管是采用队列形式,事实上,把它称

  • Java线程生命周期及转换过程

    目录 Java 线程生命周期 生命周期转换 1.从 NEW 到 RUNNABLE 2.从 RUNNABLE 到 BLOCKED 3.从 RUNNABLE 到 WAITTING 4.从 RUNNABLE 到 TIMED_WATTING 5.RUNNABLE 到 TERMINATED 总结 前言: 线程的生命周期指的是线程从创建到销毁的整个过程,通常情况下线程的生命周期有以下 5 种: 初始状态 可运行状态 运行状态 休眠状态 终止状态 它们的状态转换如下图所示:  Java 线程生命周期 Java

  • Java线程生命周期的终止与复位

    目录 Thread生命周期 生命周期概述 线程生命周期流程图 线程生命周期测试 启动线程 java中的启动 Hotspot中的启动 线程中断与复位 不要使用stop方法 使用interrupt方法 线程的复位 其他的线程复位 Thread生命周期 生命周期概述 Java的线程状态描述放在Thread类里面的枚举类State中.总共包含了6中状态(从出生到死亡). public enum State { /** * 尚未启动的线程的线程状态 (没有start) */ NEW, /** * 可运行线

  • Java中的线程生命周期核心概念

    目录 Java多线程 Java中线程的生命周期 NEW Runnable Blocked Waiting Timed Waiting Terminated 结论 前言: 在本文中,我们将详细讨论Java中的一个核心概念——线程的生命周期.我们将使用一个快速的图解,当然还有实用的代码片段来更好地理解线程执行期间的这些状态. Java多线程 在Java语言中,多线程是由线程的核心概念驱动的.线程在其生命周期中会经历各种状态: Java中线程的生命周期 java.lang.Thread类包含一个静态枚

  • java类型生命周期的详细解析

    开始阶段 装载:把二进制形式的java类型读入jvm中.1)通过该类型的完全限定名,产生一个代表该类型的二进制数据流:2)解析这个二进制数据流为方法区内的内部数据结构:3)创建一个表示该类型的java.lang.Class类的实例: 连接:把已读入的类型数据合并到虚拟机的运行时状态中.1)验证:确保java类型数据格式正确并且适用于jvm使用:2)准备:为该类型分配内存:3)解析:把常量池中的符号引用转换为直接引用: 初始化:每个类和接口在首次主动使用时初始化.为类变量赋予正确的初始值:1)如果

  • 通过代码实例解析JAVA类生命周期

    代码 public class TestClass { public static int k=0; public static TestClass t1=new TestClass("t1"); public static TestClass t2=new TestClass("t2"); public static int i=print("i"); public static int n=99; public int j=print(&qu

  • Java中Servlet的生命周期详解

    目录 Web基础和HTTP协议 什么是Servlet Servlet的生命周期 Web基础和HTTP协议 ┌─────────┐ ┌─────────┐ │░░░░░░░░░│ │O ░░░░░░░│ ├─────────┤ ├─────────┤ │░░░░░░░░░│ │ │ ├─────────┤ │ │ │░░░░░░░░░│ └─────────┘ └─────────┘ │ request 1 │ │─────────────────────>│ │ request 2 │ │───

  • Java 线程池详解及创建简单实例

    Java 线程池 最近在改进项目的并发功能,但开发起来磕磕碰碰的.看了好多资料,总算加深了认识.于是打算配合查看源代码,总结并发编程的原理. 准备从用得最多的线程池开始,围绕创建.执行.关闭认识线程池整个生命周期的实现原理.后续再研究原子变量.并发容器.阻塞队列.同步工具.锁等等主题.java.util.concurrent里的并发工具用起来不难,但不能仅仅会用,我们要read the fucking source code,哈哈.顺便说声,我用的JDK是1.8. Executor框架 Exec

  • Java 线程池详解及实例代码

    线程池的技术背景 在面向对象编程中,创建和销毁对象是很费时间的,因为创建一个对象要获取内存资源或者其它更多资源.在Java中更是如此,虚拟机将试图跟踪每一个对象,以便能够在对象销毁后进行垃圾回收. 所以提高服务程序效率的一个手段就是尽可能减少创建和销毁对象的次数,特别是一些很耗资源的对象创建和销毁.如何利用已有对象来服务就是一个需要解决的关键问题,其实这就是一些"池化资源"技术产生的原因. 例如Android中常见到的很多通用组件一般都离不开"池"的概念,如各种图片

  • Java线程的基本概念

    在之前的章节中,我们都是假设程序中只有一条执行流,程序从main方法的第一条语句逐条执行直到结束.从本节开始,我们讨论并发,在程序中创建线程来启动多条执行流,并发和线程是一个复杂的话题,本节,我们先来讨论Java中线程的一些基本概念. 创建线程 线程表示一条单独的执行流,它有自己的程序执行计数器,有自己的栈.下面,我们通过创建线程来对线程建立一个直观感受,在Java中创建线程有两种方式,一种是继承Thread,另外一种是实现Runnable接口,我们先来看第一种. 继承Thread Java中j

随机推荐