线程的状态

老生常谈

线程的状态这个话题老生常谈了,但是一定要纠正下,网上的诸多资料太乱,有的说的根本就是错的。Java线程的状态和操作系统的状态根本就是两回事,不可混淆。Java线程的状态位于上层,一个Java状态可能对应N个操作系统的线程状态。

状态枚举

中文翻译过来的状态太多叫法,还是得英文原本的叫法。

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

1、NEW:刚创建尚未启动线程。
2、RUNNABLE: 复合状态,包含有2个状态:Ready和Running。
3、BLOCKED:线程在等待锁时。
4、WAITING:调用wait、join等方法。
5、TIMED_WAITING: sleep(time)
6、TERMINATED:run方法执行结束。

JVisualVM中将状态分为运行、休眠、等待、驻留、监视。

它们几个和Thread的状态的对应关系是:

Thread类VisualVM
RUNNABLE运行
TIMED_WAITING (sleeping)休眠
TIMED_WAITING (on object monitor) WAITING (on object monitor)等待
TIMED_WAITING (parking) WAITING (parking)驻留
BLOCKED (on object monitor)监视

线程状态转换图

类加载器示意图

来自:https://www.uml-diagrams.org/java-thread-uml-state-machine-diagram-example.html

示例1

package com.sss.concurrency.thread.status;


import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

public class ThreadStatusTest1 {
    ReentrantLock lock = new ReentrantLock();
    Condition condition = lock.newCondition();

    public void test1(){
        Thread t1 = new Thread(() -> {
            try {
                System.out.println("3秒后再次运行,然后进入wait状态");
                TimeUnit.SECONDS.sleep(3);
                lock.lock();
                condition.await();
                int i = 0;
                while(i++  < 100000000){
                }
                lock.unlock();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }, "t1");

        new Thread(()->{
            try {
                TimeUnit.SECONDS.sleep(5);
                lock.lock();
                TimeUnit.SECONDS.sleep(5);
                condition.signalAll();
                lock.unlock();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        },"notify线程").start(); //notify线程

        System.out.println(t1.getState());
        t1.start();
        while(true){
            System.out.println(t1.getState());
            try {
                TimeUnit.SECONDS.sleep(1);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }

    public static void main(String[] args) {
        new ThreadStatusTest1().test1();
    }
}

NEW
RUNNABLE
3秒后再次运行,然后进入wait状态
TIMED_WAITING
TIMED_WAITING
WAITING
WAITING
WAITING
WAITING
WAITING
WAITING
WAITING
TERMINATED
TERMINATED
TERMINATED
TERMINATED

Process finished with exit code -1

第一个示例演示了从NEW到RUNNABLE再到TIMED_WAITING,最后TERMINATED的转变

示例2

package com.sss.concurrency.thread.status;

import java.util.concurrent.TimeUnit;

public class ThreadStatusTest2 implements Runnable{
    public static void main(String[] args) {
        ThreadStatusTest2 threadStatusTest2 = new ThreadStatusTest2();
        Thread t1 = new Thread(threadStatusTest2, "t1");
        Thread t2 = new Thread(threadStatusTest2, "t2");
        new Thread(()->{
            while(true){
                System.out.println("t1.state=" + t1.getState());
                System.out.println("t2.state=" + t2.getState());
                try {
                    TimeUnit.SECONDS.sleep(1);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }).start();
        t1.start();
        t2.start();
    }

    @Override
    public void run() {
        synchronized (this){
            try {
                TimeUnit.SECONDS.sleep(3);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
}

t1.state=RUNNABLE
t2.state=BLOCKED
t1.state=TIMED_WAITING
t2.state=BLOCKED
t1.state=TIMED_WAITING
t2.state=BLOCKED
t1.state=TERMINATED
t2.state=TIMED_WAITING
t1.state=TERMINATED
t2.state=TIMED_WAITING
t1.state=TERMINATED
t2.state=TIMED_WAITING
t1.state=TERMINATED
t2.state=TERMINATED

第二个示例演示了线程状态从RUNNABLE–>BLOCKED---->TERMINATED的转变。

示例3

package com.sss.concurrency.thread.status;

import java.io.*;
import java.net.ServerSocket;
import java.net.Socket;
import java.nio.channels.FileChannel;
import java.util.concurrent.TimeUnit;

public class ThreadStatusTest3 implements Runnable{
    public static void main(String[] args) {
        ThreadStatusTest3 threadStatusTest2 = new ThreadStatusTest3();
        Thread t1 = new Thread(threadStatusTest2, "t1");
        new Thread(()->{
            while(true){
                System.out.println("t1.state=" + t1.getState());
                try {
                    TimeUnit.SECONDS.sleep(1);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }).start();
        t1.start();
    }

    @Override
    public void run() {
        ServerSocket server = null;
        try {
            server = new ServerSocket(8000);
            System.out.println("服务器准备就绪~");
            System.out.println("服务器信息:" + server.getInetAddress() + " P:" + server.getLocalPort());
            // 等待客户端连接
            while(true) {
            }
        } catch (IOException e) {
            e.printStackTrace();
        }

    }
}

t1.state=RUNNABLE
服务器准备就绪~
服务器信息:0.0.0.0/0.0.0.0 P:8000
t1.state=RUNNABLE
t1.state=RUNNABLE
t1.state=RUNNABLE
t1.state=RUNNABLE
t1.state=RUNNABLE

第3个示例说明了网络IO的阻塞,线程状态不是BLOCKED,而是RUNNABLE。
就算是IO阻塞或者网路阻塞,对于JVM而言,程序是在运行啊。JVM把网卡啊、cpu也好,都认为有资源在为线程服务。

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值