一文详解Java线程的6种状态与生命周期

一文详解Java线程的6种状态与生命周期

线程生命周期

Java线程的生命周期可以分为6种不同的状态:
1. New(新建): 当线程对象被创建时,它处于新建状态,但还没有开始运行。
2. Runnable(可运行): 当调用start()方法时,线程进入可运行状态,等待被线程调度器分派时间片得以运行。
3. Blocked(阻塞): 线程被阻塞于某一个等待状态,如等待一个I/O操作的完成或等待获取一个锁。
4. Waiting(等待): 线程处于一个无限期的等待状态,直到线程被特定的notify()或notifyAll()方法唤醒。
5. Timed Waiting(超时等待): 线程等待一个指定的时间,在等待的时间到达之前可以通过notify()或notifyAll()方法唤醒。
6. Terminated(终止): 线程已经执行完毕或发生了一个异常而终止。

线程状态转换

Java线程的状态可以不断地改变,具体状态转换如下:

  1. New -> Runnable:当调用了线程对象的start()方法时,线程进入可运行状态,等待系统的线程调度器来调度该线程执行。
  2. Runnable -> Running:当线程被分配到CPU时间片后,线程开始执行run()方法,进入Running状态。
  3. Running -> Runnable:当线程在执行时,遇到了某个条件(如睡眠时间结束、I/O完成、wait()被notify()方法唤醒)无法继续执行时,线程自动切换成可运行状态。
  4. Running -> Blocked:当线程试图获取一个被其他线程持有的锁或者在等待某个输入/输出操作完成时,该线程会进入阻塞状态(Blocked)。
  5. Blocked -> Runnable:当线程持有锁的同时,马上就会调用synchronized方法/块(等待另外一个信号),该线程会进入阻塞状态(Blocked),等待另外一个信号。
  6. Running -> Waiting:线程执行wait()方法,处于 Waiting 状态,在被notify() 方法唤醒之前等待状态不会被改变。
  7. Waiting -> Runnable:线程被notify()方法唤醒,进入 Runnable 状态。
  8. Running -> Timed Waiting:线程执行sleep()方法或wait(long)方法,进入Timed Waiting状态,知道超时或被唤醒。
  9. Timed Waiting -> Runnable:线程等待超时或被唤醒,回归Runnable状态。
  10. 任何状态 -> Terminated:当线程执行完毕(run()方法完成),或者因为异常退出时,该线程被置于终止状态(Terminated)。

示例说明

示例1:线程阻塞

public class ThreadBlockTest {
    public static void main(String[] args) {
        Object lock = new Object();
        Thread t1 = new Thread(new Runnable() {
            @Override
            public void run() {
                synchronized(lock) {
                    System.out.println("t1获取到锁,开始执行;");
                    try {
                        lock.wait();    // 使当前线程进入等待状态
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    System.out.println("t1被唤醒了,重新获取锁,继续执行");
                }
            }
        });
        Thread t2 = new Thread(new Runnable() {
            @Override
            public void run() {
                synchronized(lock) {
                    System.out.println("t2获取到锁,开始执行;");
                    try {
                        Thread.sleep(2000);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    lock.notify();  // 唤醒正在等待的线程
                    System.out.println("t2执行完成,释放锁");
                }
            }
        });
        t1.start();
        t2.start();
    }
}

以上代码中,我们创建了两个线程t1和t2,t1运行后,调用lock.wait()方法使自己处于阻塞状态,等待被唤醒。t2获得锁之后,先延时2秒钟,然后调用lock.notify()方法,唤醒正在等待的线程t1,使其从wait()方法阻塞的状态恢复到Runnable状态。

示例2:线程等待

public class ThreadWaitTest {
    public static void main(String[] args) {
        Object lock = new Object();
        Thread t1 = new Thread(new Runnable() {
            @Override
            public void run() {
                synchronized(lock) {
                    System.out.println("t1获取到锁,开始执行");
                    try {
                        lock.wait(5000);    // 使当前线程进入等待状态,超时时间为5秒
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    System.out.println("t1被唤醒了,重新获取锁,继续执行");
                }
            }
        });
        t1.start();
    }
}

以上代码中,我们创建一个线程t1,在synchronized(lock)代码块中,调用lock.wait(5000)方法,使当前线程进入超时等待状态,等待5秒钟。5秒钟后,如果没有其他线程调用lock.notify()方法来唤醒当前线程,则t1从Timed Waiting状态转换为Runnable状态,继续执行。

本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:一文详解Java线程的6种状态与生命周期 - Python技术站

(0)
上一篇 2023年5月19日
下一篇 2023年5月19日

相关文章

  • SpringMvc @Valid如何抛出拦截异常

    Spring MVC 中的 @Valid 注解可以用来验证提交的数据是否满足指定的规则和条件,但是如果数据不符,则需要抛出异常给前端。 下面是使用 @Valid 注解实现异常拦截的步骤: 在 Controller 的方法参数中添加注解 @Valid 和 BindingResult 对象。 编写数据验证规则,通常是在数据实体类中使用注解编写。 在 Contro…

    Java 2023年5月27日
    00
  • JS携带参数实现页面跳转功能

    JS携带参数实现页面跳转功能攻略 在开发Web应用时,经常需要跳转到另一个页面,并携带一些参数。本文将详细讲解如何使用JavaScript实现这个功能。 实现思路 在JavaScript中,可以使用window.location对象实现页面的跳转。为了携带参数,可以将参数附加在URL的后面,形如http://example.com/?key1=value1&…

    Java 2023年6月15日
    00
  • Java for循环详解

    Java for循环详解 在Java中,for循环是一种常用的迭代结构。它提供了一种在满足特定条件的情况下,重复执行某段代码的方法。下面我们来详细讲解Java for循环的语法和用法。 语法 Java for循环的语法如下: for (initialExpression; testExpression; updateExpression) { // 要执行的…

    Java 2023年5月26日
    00
  • springboot @Controller和@RestController的区别及应用详解

    Spring Boot @Controller和@RestController的区别及应用详解 在Spring Boot中,@Controller和@RestController是两个常用的注解,用于处理HTTP请求。虽然它们都可以用于处理请求,但它们之间有一些区别。在本文中,我们将详细讲解@Controller和@RestController的区别及应用详…

    Java 2023年5月15日
    00
  • JAVA中的for循环几种使用方法讲解

    JAVA中的for循环几种使用方法讲解 在Java中,for循环是最常用的循环结构之一。它可以重复执行代码块,根据不同的循环条件可以有多种使用方式。 基本的for循环 最基本的for循环有三个部分,分别是循环变量初始化、循环条件和循环变量的更新。语法如下: for (循环变量初始化; 循环条件; 循环变量的更新) { // 循环体代码块 } 其中,循环变量初…

    Java 2023年5月26日
    00
  • java快速生成数据库文档详情

    下面我将为你详细讲解“java快速生成数据库文档详情”的完整攻略。 1. 环境准备 首先,我们需要安装Java开发环境,JDK和JRE都需要安装。然后,我们需要下载并安装MySQL数据库。 2. 导入数据库表结构 将需要生成文档的数据库表结构信息导出为.sql文件,然后使用MySQL命令行工具或可视化工具导入到本地MySQL数据库中。 mysql -u ro…

    Java 2023年5月19日
    00
  • SpringMVC底层执行流程及原理解析

    以下是关于“SpringMVC底层执行流程及原理解析”的完整攻略,其中包含两个示例。 SpringMVC底层执行流程及原理解析 SpringMVC是一个基于MVC架构的Web框架,它提供了一种灵活、高效的方式来开发Web应用程序。在SpringMVC中,请求的处理流程可以分为以下几个步骤: 客户端发送请求到DispatcherServlet。 Dispatc…

    Java 2023年5月16日
    00
  • 站长必看!赚钱网站资源贴

    站长必看!赚钱网站资源贴 一、引言 作为一个网站站长,赚钱是我们始终追求的一个目标。然而,在众多的网络赚钱方法中选择适合自己的方式并不是一件容易的事情。因此,本文针对网站站长提供了一些有用的资源和建议,帮助您更加容易地赚钱。 二、网站广告 网站广告是一种常见的赚钱方式,下面列出几种常见的广告形式: 1. 横幅广告 横幅广告是在页面的顶部或底部显示的广告条,通…

    Java 2023年6月16日
    00
合作推广
合作推广
分享本页
返回顶部