首页 > 编程语言 >Java中线程的生命周期

Java中线程的生命周期

时间:2022-11-08 11:31:19浏览次数:42  
标签:状态 生命周期 Java Thread t1 线程 new 中线 public

Java中线程的生命周期

1 介绍

本篇文章我们讨论下Java中的一个非常核心的概念:线程的生命周期。在Java编程语言中,多线程编程非常重要。线程从创建到销毁是有生命周期的,在线程的生命周期中,线程会经历多种状态(state)。

2 线程状态说明以及状态流转图

​java.lang.Thread​​类中有一个静态的枚举类:​​State​​,用来表示线程各种可能的状态:

public enum State {
/**
* NEW状态表示线程新创建,仍不能开始运行。
*/
NEW,

/**
* RUNNABLE表示线程可运行(runnable or ready to run),有可能正在运行,或者正在资源ready,比如CPU调度。
*/
RUNNABLE,

/**
* BLOCKED表示线程正在等待监视器锁(monitor lock),获取到监视器锁后可以进入同步代码块或者同步方法(synchronized block/method),当然可能是首次等待,也可能是调用Object.wait()等待之后再被唤醒(Object.notify()或者Object.notifyAll())后,因为唤醒后一般不能直接进入Runnable状态,需要重写争抢监视器锁,这时仍然是BLOCKED状态。
*/
BLOCKED,

/**
* WAITING状态表示当前线程正在等待其他线程的一些动作(无超时时间的等待),包括如下三个场景:
* Object.wait()调用之后等待其他线程调用Object.notify()或者Object.notifyAll()
* Thread.join()调用之后等待指定的线程终止(进入TERMINATED状态)
* LockSupport.park()调用之后等待等待其他线程调用LockSupport.unpark(thread)
*/
WAITING,

/**
* TIMED_WAITING状态表示当前线程在限定时间内等待其他线程的一些动作,包括如下几个场景:
* Thread.sleep
* Object.wait指定等待时间
* Thread.join指定等待时间
* LockSupport.parkNanos
* LockSupport.parkUntil
*/
TIMED_WAITING,

/**
* TERMINATED表示终止状态,线程已经执行完成。
*/
TERMINATED;
}
复制代码

线程的可能状态流转图(状态机)如下所示:

Java中线程的生命周期_生命周期

注意上面的​​Blocked​​状态,线程调用​​Object.wait()​​等待之后会进入​​WAITING​​或​​TIMED_WAITING​​状态,而再被唤醒(​​Object.notify()​​或者​​Object.notifyAll()​​)后,由于唤醒后一般不能直接进入​​Runnable​​状态,需要重写争抢监视器锁,这时仍然是先进入​​BLOCKED​​状态。

3 线程各状态实战举例

3.1 NEW

​NEW​​状态表示线程新创建,仍不能开始运行。当调用了线程的​​start()​​方法后线程才开始运行。下面的代码表示新创建的线程处于​​NEW​​状态:

Runnable runnable = new Runnable() {
@Override
public void run() {
System.out.println("线程任务运行中...");
}
};
Thread thread = new Thread(runnable);
System.out.println(thread.getState());
复制代码

运行结果如下:

Java中线程的生命周期_java_02

3.2 Runnable

​RUNNABLE​​表示线程可运行(runnable or ready to run),有可能正在运行,或者正在资源ready,比如CPU调度。在多线程环境下,JVM中的线程调度器给每个线程分配一定的时间片去执行,执行完分配的之后之后,换为其他线程执行(分时复用机制)。我们继续基于前面的代码,把线程启动起来,然后看下线程的状态:

Runnable runnable = new Runnable() {
@Override
public void run() {
System.out.println("线程任务运行中...");
}
};
Thread thread = new Thread(runnable);
thread.start();
System.out.println(thread.getState());
复制代码

运行结果如下:

Java中线程的生命周期_ide_03

有一点需要注意:由于线程启动之后可能非常快就直接执行完,因此可能输出​​TERMINATED​​状态。

3.3 Blocked

当一个线程等待获取监视器锁(monitor lock)的时候,会处于​​BLOCKED​​状态,之所以要等待获取监视器锁,是因为当前监视器锁正在被其他线程占有。下面我们复现该线程状态:

public class TestMain {
public static void main(String[] args) throws InterruptedException {
Thread t1 = new Thread(new DemoBlockedRunnable());
Thread t2 = new Thread(new DemoBlockedRunnable());
t1.start();
t2.start();
Thread.sleep(1000);
System.out.println(t2.getState());
System.exit(0);
}
}

class DemoBlockedRunnable implements Runnable {
@Override
public void run() {
commonResource();
}

public static synchronized void commonResource() {
while(true) {
// Infinite loop to mimic heavy processing
// 't1' won't leave this method
// when 't2' try to enter this
}
}
}
复制代码

输出如下:

Java中线程的生命周期_ide_04

上述代码中,由于​​t1​​先抢占了​​类DemoBlockedRunnable​​上的监视器锁,并且​​t1​​进入了无限循环,导致​​t2​​一直在等待获取监视器锁,因此打印​​t2​​的线程状态为​​BLOCKED​​。

3.4 Waiting

WAITING状态表示当前线程正在等待其他线程的一些动作(无超时时间的等待),包括如下三个场景:

  1. object.wait()调用之后等待其他线程调用Object.notify()或者Object.notifyAll();
  2. thread.join()调用之后等待指定的线程终止(进入TERMINATED状态);
  3. LockSupport.park()调用之后等待等待其他线程调用LockSupport.unpark(thread);

下面我们复现该线程状态:

public class TestMain {
public static void main(String[] args) throws InterruptedException {
Thread t1 = new Thread(new Runnable1());
Thread t2 = new Thread(new Runnable2(t1));
t1.start();
t2.start();
Thread.sleep(1000);
System.out.println(t2.getState());
}
}

class Runnable1 implements Runnable {
@Override
public void run() {
System.out.println("Runnable1 begin run...");
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("Runnable1 end run...");
}
}

class Runnable2 implements Runnable {
private Thread runnable1;
public Runnable2(Thread runnable1) {
this.runnable1 = runnable1;
}
@Override
public void run() {
System.out.println("Runnable2 begin run...");
try {
runnable1.join();
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("Runnable2 end run...");
}
}
复制代码

输出如下:

Java中线程的生命周期_ide_05

这里由于线程​​t2​​调用了​​thread.join()​​,因此陷入​​WAITING​​状态。

3.5 Timed Waiting

TIMED_WAITING状态表示当前线程在限定时间内等待其他线程的一些动作,包括如下几个场景:

  1. Thread.sleep(long mills)
  2. object.wait(int timeout)
  3. thread.join(long mills)
  4. LockSupport.parkNanos
  5. LockSupport.parkUntil
public class TestMain {
public static void main(String[] args) throws InterruptedException {
Thread t1 = new Thread(new Runnable() {
@Override
public void run() {
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
});
t1.start();
Thread.sleep(1000);
System.out.println(t1.getState());
}
}
复制代码

输出如下:

Java中线程的生命周期_java_06

这里由于线程​​t1​​调用了​​Thread.sleep(2000)​​,因此在等待期内的状态为​​TIMED_WAITING​​。

3.6 Terminated

​TERMINATED​​是线程终止状态,线程完成执行或者异常终止后都会处于​​TERMINATED​​状态。

public class TestMain {
public static void main(String[] args) throws InterruptedException {
Thread t1 = new Thread(new Runnable() {
@Override
public void run() {
System.out.println("t1 running begin..");
System.out.println("t1 running end..");
}
});
t1.start();
Thread.sleep(1000);
System.out.println(t1.getState());
}
}
复制代码

输出如下:

Java中线程的生命周期_ide_07

4 总结

线程是Java多线程编程的基础,本文讨论了Java中线程的生命周期,以及生命周期中可能出现的6种状态,每种状态都举例进行了说明。

标签:状态,生命周期,Java,Thread,t1,线程,new,中线,public
From: https://blog.51cto.com/u_15773567/5832430

相关文章

  • Day05:Java运算时的类型转换
    Java运算时的类型转换在Java运算时,不同的数据类型之间可以进行加减乘除的预算;但是,不同类型的数据需要先转换为同一类型才能够运算强制类型转换从字节大小排序数据类型......
  • 【面试题】Java OOP 面试题
    JavaOOP面试题 1.shorts1=1;s1=s1+1;有错吗?shorts1=1;s1+=1;有错吗?首先我们需要了解大的数据类型向小的数据类型转换需要强制类型转换第一条语句中s1......
  • Java 调用Dll
    Java中怎么能调用到dll中的函数呢?关键是java中生的本地函数名参数和dll中的本地函数名参数一模一样。这个程序是java中调用dll中的求和函数。一,java代码部分操作1.新建工程......
  • 8 个常用的JavaScript 比较运算符,你一定要知道
    英文|https://javascript.plainenglish.io/the-8-javascript-comparison-operators-you-need-to-know-cb952090d087翻译| 杨小爱1、相等我们将讨论的第一个比较运算符是......
  • 【JavaScript 教程】第六章 数组03— Stack :使用 Array 的push()和pop()方法实现堆栈
    英文 | https://www.javascripttutorial.net/译文|杨小爱在上节,我们学习了JavaScriptArray length属性以及如何正确处理它,错过的小伙伴可以点击文章《​​【JavaScrip......
  • Java 学习的总结
    1.JVM相关(包括了各个版本的特性)对于刚刚接触Java的人来说,JVM相关的知识不一定需要理解很深,对此里面的概念有一些简单的了解即可。不过对于一个有着3年以上Java经验......
  • Java枚举
    Java枚举目录Java枚举  知识点  概念  枚举的方法  枚举的特性  枚举的应用场景  EnumSet和EnumMapJava枚举知识点概念enum 的全称为enumeration,是JDK......
  • Java 散乱脚本整理
     杀死所有java进程  taskkill/f/t/imjava.exe 清理打包@echooffecho.echo[信息]清理工程target生成路径。echo.%~d0cd%~dp0cd..callmvnc......
  • java web基础
    1.JavaWeb模块结构JSP文件和AXPX文件类似,路径和URL一一对应,都会被动态编译为单独class。JavaWeb和ASP.NET的核心是分别是Servlet和IHttpHandler接口,因此无论是基础的Pag......
  • JavaScript数组去重—ES6的两种方式
    说明JavaScript数组去重这个问题,经常出现在面试题中,以前也写过一篇数组去重的文章,(JavaScript数组去重的多种方法原理详解)但感觉代码还是有点不够简单,今天和大家再说两种......