首页 > 编程语言 >Java线程状态

Java线程状态

时间:2023-09-04 23:03:51浏览次数:54  
标签:状态 java Thread WAITING state 线程 thread1 Java

目录

Java线程状态

Java 中有六个线程状态:

// Thread.State
public enum State {
    NEW,
    RUNNABLE,
    BLOCKED,
    WAITING,
    TIMED_WAITING,
    TERMINATED;
}

这些线程状态表示线程的生命周期, 其状态变化图如下:

线程生命周期

NEW

每个线程在新建之后, 调用 start 方法前, 都处于 NEW 状态.

start 方法本身并不修改线程状态, 而是其中调用的 start0native 方法, 在 jdk 的源码中最终调用了下面这段代码修改的线程状态:

void Thread::start(Thread* thread) {
  // Start is different from resume in that its safety is guaranteed by context or
  // being called from a Java method synchronized on the Thread object.
  if (thread->is_Java_thread()) {
    // Initialize the thread state to RUNNABLE before starting this thread.
    // Can not set it after the thread started because we do not know the
    // exact thread state at that time. It could be in MONITOR_WAIT or
    // in SLEEPING or some other state.
    java_lang_Thread::set_thread_status(JavaThread::cast(thread)->threadObj(),
                                        JavaThreadStatus::RUNNABLE);
  }
  os::start_thread(thread);
}

RUNNABLE

start 之后, 线程状态就变为了 RUNNABLE, RUNNABLE 不代表线程正在运行, 也可能是在等待CPU或IO资源.

例如:

public class Test {
    public static void main(String[] args) throws Exception {
        System.in.read();
    }
}

System.in.read() 将让线程暂停运行直到控制台输入任何字符, 但此时通过 jstack 观察到线程状态是 RUNNABLE.

"main" #1 [16836] prio=5 os_prio=0 cpu=796.88ms elapsed=31.46s tid=0x0000022a267f19d0 nid=16836 runnable  [0x000000ec5d2ff000]
   java.lang.Thread.State: RUNNABLE
Thread: 0x0000022a267f19d0  [0x41c4] State: _at_safepoint _at_poll_safepoint 0
   JavaThread state: _thread_in_native
	at java.io.FileInputStream.readBytes(java.base/Native Method)
	at java.io.FileInputStream.read(java.base/FileInputStream.java:287)
	at java.io.BufferedInputStream.fill(java.base/BufferedInputStream.java:291)
	at java.io.BufferedInputStream.implRead(java.base/BufferedInputStream.java:325)
	at java.io.BufferedInputStream.read(java.base/BufferedInputStream.java:312)
	at Test.main(Test.java:4)

BLOCKED

处于 BLOCKED 状态的线程正在等待取得锁.

当线程进入 sychronized 代码块/方法, 或调用 Object.wait() 后重新进入 synchronized 代码块/方法的时候, 会处于阻塞状态.

Java 线程的 BLOCKED 状态与一般所说的阻塞存在一定区别, BLOCKED 状态仅代表Java 线程在等待取得锁, 而一般所说的阻塞通常指线程暂停运行, 即上文中提到的System.in.read() 导致的线程暂停运行等待IO的情况在很多时候也称之为阻塞. 为避免歧义, 下文中的阻塞指线程暂停运行.

WAITING

处于 WAITING 状态的线程等待其它线程的通知.

调用 Object.wait, Thread.join, LockSupport.park 会导致线程进入 WAITING 状态, 对应的需要调用 Object.notifyObject.notifyAll, 线程终止, LockSupport.unpark 解除线程的 WAITING 状态. WAITING 状态解除的线程并不一定会变为 RUNNABLE 状态, 如 Object.wait 的线程会变为 BLOCKED 状态直到取得锁才能变为 RUNNABLE.

TIMED_WAITING

逻辑同 WAITING, 不同在于等待一定时间后没有通知就自动恢复.

相关的调用有:

  • Thread.sleep
  • Object.wait(long timeout)
  • Thread.join(long timeout)
  • LockSupport.parkNanos
  • LockSupport.parkUntil

测试

下面这段代码输出线程不同的状态

public class Main {

  private static Thread thread1 = null;
  private static Thread thread2 = null;

  public static void main(String[] args) throws InterruptedException {
    thread1 = new Thread(() -> {
      // RUNNABLE
      System.out.println("Thread1 running state: " + thread1.getState());
      try {
        // 等待一会, 让thread2取得锁
        Thread.sleep(1000);
      }
      catch (InterruptedException e) {
        throw new RuntimeException(e);
      }
      synchronized (Main.class) {
        // thread1 取得锁, 此时thread2 调用了 Object.wait()
        System.out.println("Thread2 Object.wait() state: " + thread2.getState());
        // 唤醒thread2
        Main.class.notify();
        // thread2 从等待状态被唤醒, 接着等待锁
        System.out.println("Thread2 wait lock state: " + thread2.getState());
      }
    });
    System.out.println("Thread1 new state: " + thread1.getState());
    thread2 = new Thread(() -> {
      synchronized (Main.class) {
        // thread1 正在sleep
        System.out.println("Thread1 sleep state: " + thread1.getState());
        try {
          // thread1 等待锁
          Thread.sleep(1000);
          System.out.println("Thread1 acquiring lock state: " + thread1.getState());
        }
        catch (InterruptedException e) {
          throw new RuntimeException(e);
        }
        try {
          // 让出锁, 让thread1 执行
          Main.class.wait();
          // thread1 执行完, thread2 取得锁恢复执行
        }
        catch (InterruptedException e) {
          throw new RuntimeException(e);
        }
      }
      // thread1 已经结束
      System.out.println("Thread1 run out state: " + thread1.getState());

    });
    thread1.start();
    // 保证thread1先执行
    Thread.sleep(500);
    thread2.start();
  }
}

输出:

Thread1 new state: NEW
Thread1 running state: RUNNABLE
Thread1 sleep state: TIMED_WAITING
Thread1 acquiring lock state: BLOCKED
Thread2 Object.wait() state: WAITING
Thread2 wait lock state: BLOCKED
Thread1 run out state: TERMINATED

标签:状态,java,Thread,WAITING,state,线程,thread1,Java
From: https://www.cnblogs.com/wymc/p/17678210.html

相关文章

  • Java实现多种单例模式
    packagecom.java3y.austin.test.Mode;importjava.util.HashSet;importjava.util.concurrent.atomic.AtomicBoolean;//饿汉式单例classSingleton1{privateSingleton1(){}privatestaticfinalSingleton1singleton1=newSingleton1();publ......
  • 《C++》11新特性--多线程
    thread创建线程,不会阻塞主线程thread成员函数voidthread::join();阻塞线程,当前线程执行完毕才会往下执行boolthread::joinble();线程是否可以连接,返回voidthread::detach();分离主线程和子线程的关联voidprintI(){for(size_ti=0;i<100;i++){std::c......
  • 如何在Java中连接MySQL数据库并实现增删改查操作
    要在Java中连接MySQL数据库并实现增删改查操作,你需要遵循以下步骤:导入所需的Java库:你需要导入Java中与MySQL连接和操作相关的库。常用的库包括JDBC(JavaDatabaseConnectivity)和MySQL驱动程序。importjava.sql.*;建立数据库连接:使用JDBC连接MySQL数据库,你需要提供数据库的URL、用......
  • SpringBoot项目报java.lang.IllegalStateException: Cannot load configuration class
    报错摘要:java.lang.IllegalStateException:Cannotloadconfigurationclass:com.imooc.demo.DemoApplication,Causedby:java.lang.ExceptionInInitializerError:null,Causedby:org.springframework.cglib.core.CodeGenerationException:java.lang.reflect.I......
  • ##线程面试题##
    一.java中线程实现几种实现方式在Java中实现多线程一共有四种方式:(1)继承Thread类(2)实现Runable接口(3)实现Callable接口(4)线程池1.继承java.lang.Thread,重写run方法,启动线程,调用start()方法>2.实现java.lang.Runnable接口,实现run方法3.实现Callable接口(JDK8新特性)该方法效率较低,......
  • JavaWeb项目3.0之后创建web项目
    在上一篇文章中我们看到创建web项目的过程,但是在web3.0之后有了注解的加入,可以更简单的创建Web项目。选择自己创建的maven项目,填写项目名称。 在项目中添加web模块 添加对应的打包形式 配置tomcat 添加对应模块  最为重要的我们不需要web.xml的繁琐......
  • 线程池至少需要线程数——23秋招招行网络科技第一批技术测评_后端(c++)
    题目:有n个计划,每个计划有开始,结束时间,求线程池最少需要多少个线程?例:输入:2,[[1,2],[3,4]],输出:1输入:2, [[1,3],[2,4]],输出:2 思路:贪心算法PS:其实我不是很理解下面代码第11行,分别对a,b数组排序1#include<bits/stdc++.h>2usingnamespacestd;34intma......
  • java基础-数组-day06
    1.引入数组录入10个学生的成绩求和求平均importjava.util.Scanner;publicclassTestArray01{publicstaticvoidmain(String[]args){ Scannersc=newScanner(System.in); intsum=0; for(inti=1;i<=10;i++){ System.out.println("请输入第"+i+"......
  • Java开学测试
    二、系统背景:某机械有限公司为了公司进一步的发展,需要实现企业数字化管理,新引进一套企业信息管理系统(ERP),由于该产品缺乏入库功能,特委托石家庄铁道大学信息科学与技术学院前进22软件有限公司开发仓库管理功能。二、 数据结构要求:(5分)1、定义WarehouseInformation类,其中包括九个......
  • 无涯教程-JavaScript - DMAX函数
    描述DMAX函数返回列表或数据库中符合您指定条件的列中的最大数字。语法DMAX(database,field,criteria)争论Argument描述Required/Optionaldatabase组成列表或数据库的单元格范围。数据库是相关数据的列表,其中相关信息的行是记录,数据的列是字段。列表的第一行包......