线程的状态及转换

线程状态定义

Thread里面关于线程状态的定义:

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

先看一个线程的状态图:

图片[1]-线程的状态及转换-不念博客

NEW,TERMINATED

线程对象刚创建,还未执行start方法前的状态为NEW,初始状态;在线程执行完run方法里面的内容后的状态为TERMINATED,终止状态,线程已经执行完退出。

我们在JVM中监控线程时,这两个状态是看不到的。

RUNNABLE

线程对象执行完start方法后的状态,细分为Ready和Running两个形态,线程在抢到CPU时间片时,处于Running运行状态,执行run方法中的代码;

在未抢到CPU时间片或CPU时间片被操作系统分配给了其它线程时,线程处于Ready状态,等待获取CPU时间片执行线程。

BLOCKED

运行中的线程,在遇到synchronized代码块或方法时,等待获取锁对象时的状态,此状态表示线程不具备CPU执行资格,也没有CPU执行权限。

故此状态不占用CPU资源,等待获取对象锁后,线程再进入Ready状态。

本状态属于阻塞状态的一种,即等待获取锁对象时被阻塞。

WAITING

运行中的线程,在执行以下方法Object.wait()、 Thread.join()、LockSupport.park()时,状态由RUNNABLE变为WAITING。

此时线程不再占用CPU资源,直到被notify()后,再进入Ready状态,等待抢夺获取CPU时间片。

本状态属于阻塞状态的一种,即等待另一个线程执行某种操作之后,再继续执行自身线程。

下面为WAITING状态的代码:


class QueMsg{
    private int num = 0;

    public int getNum() {
        return num;
    }

    public synchronized int consumeMsg(){
        if(num>0) {
            return num--;
        }else{
            return 0;
        }
    }

    public void addMsg(int num){
        this.num += num;
    }
}

public void testWaiting(){
    QueMsg msg = new QueMsg();
    Thread consumer_a = new Thread(()->{
        while(msg.getNum() == 0){
            try {
                synchronized (msg) {
                    msg.wait();
                }
            }catch(Exception e){
                e.printStackTrace();
            }
            int m = msg.consumeMsg();
            if(m>0) {
                System.out.println("Consumer-A 当前状态:"+Thread.currentThread().getState()+" ---收到一条消息:" + m + " 退出");
                break;
            }
        }
    }, "Consumer-A");

    Thread consumer_b = new Thread(()->{
        while(msg.getNum() == 0){
            try {
                synchronized (msg) {
                    msg.wait();
                }
            }catch(Exception e){
                e.printStackTrace();
            }
            int m = msg.consumeMsg();
            if(m>0) {
                System.out.println("Consumer-B 当前状态:"+Thread.currentThread().getState()+" ---收到一条消息:" + m + " 退出");
                break;
            }
        }
    }, "Consumer-B");

    Thread producer = new Thread(()->{
        try {
            Thread.currentThread().sleep(10L);
        }catch(Exception e){
            e.printStackTrace();
        }
        msg.addMsg(1);
        System.out.println("Producer-C 发送一条消息,当前消息数量:"+msg.getNum());
        synchronized (msg) {
            msg.notifyAll();
        }
        try {
            Thread.currentThread().sleep(20L);
        }catch(Exception e){
            e.printStackTrace();
        }
        msg.addMsg(1);
        System.out.println("Producer-C 发送一条消息,当前消息数量:"+msg.getNum());
        synchronized (msg) {
            msg.notifyAll();
        }
    }, "Producer-C");
    System.out.println("Consumer_A创建后的状态:"+consumer_a.getState());
    System.out.println("Consumer_B创建后的状态:"+consumer_b.getState());
    consumer_a.start();
    System.out.println("Consumer_A在调用start后的状态:"+consumer_a.getState());
    consumer_b.start();
    System.out.println("Consumer_B在调用start后的状态:"+consumer_b.getState());
    producer.start();
    try {
        Thread.currentThread().sleep(5L);
    }catch(Exception e){
        e.printStackTrace();
    }
    System.out.println("--------------------------------------");
    System.out.println("Consumer_A 当前的状态:"+consumer_a.getState());
    System.out.println("Consumer_B 当前的状态:"+consumer_b.getState());
    try {
        Thread.currentThread().sleep(10L);
    }catch(Exception e){
        e.printStackTrace();
    }
    System.out.println("--------------------------------------");
    System.out.println("Consumer_A 当前的状态:"+consumer_a.getState());
    System.out.println("Consumer_B 当前的状态:"+consumer_b.getState());
    try {
        Thread.currentThread().sleep(40L);
    }catch(Exception e){
        e.printStackTrace();
    }
    System.out.println("--------------------------------------");
    System.out.println("Consumer_A 当前的状态:"+consumer_a.getState());
    System.out.println("Consumer_B 当前的状态:"+consumer_b.getState());
}

运行结果:


Consumer_A创建后的状态:NEW
Consumer_B创建后的状态:NEW
Consumer_A在调用start后的状态:RUNNABLE
Consumer_B在调用start后的状态:RUNNABLE
--------------------------------------
Consumer_A 当前的状态:WAITING
Consumer_B 当前的状态:WAITING
Producer-C 发送一条消息,当前消息数量:1
Consumer-B 当前状态:RUNNABLE ---收到一条消息:1 退出
--------------------------------------
Consumer_A 当前的状态:WAITING
Consumer_B 当前的状态:TERMINATED
Producer-C 发送一条消息,当前消息数量:1
Consumer-A 当前状态:RUNNABLE ---收到一条消息:1 退出
--------------------------------------
Consumer_A 当前的状态:TERMINATED
Consumer_B 当前的状态:TERMINATED


进程已结束,退出代码 0

TIMED_WAITING

运行中的线程,在执行以下方法Object.wait(long),、Thread.sleep(long)、 Thread.join(long)、LockSupport.parkNanos()、LockSupport.parkUntil()时,状态由RUNNABLE变为TIMED_WAITING。

此时线程不再占用CPU资源,直到到了超时时间或被notify()后,再进入Ready状态,等待抢夺获取CPU时间片。

本状态属于阻塞状态的一种,即等待另一个线程执行某种操作之后,再继续执行自身线程。

下面为NEW、RUNNABLE、BLOCKED、WAITING、TERMINATED状态的代码


@Test
public void testStates(){
    Thread tha =  new Thread(()->{
        try {
            Thread.sleep(30L);
        }catch (Exception e){
            e.printStackTrace();
        }
        syncMethod();
    }, "Thread-A");

    Thread thb =  new Thread(()->{
        syncMethod();
    }, "Thread-B");

    System.out.println("Thread-A 线程刚创建后的状态 : " +tha.getState());
    tha.start();
    thb.start();
    System.out.println("Thread-A 线程执行start方法后的状态 : "+tha.getState());
    try {
        Thread.sleep(40L);
    }catch(Exception e){
        e.printStackTrace();
    }
    System.out.println("Thread-A 线程等待执行ayncMehtod时的状态 : "+tha.getState());
    try {
        Thread.sleep(30L);
    }catch(Exception e){
        e.printStackTrace();
    }
    System.out.println("Thread-A 线程执行asyncMehtod后线程等待50S时的状态 : "+tha.getState());

    try {
        Thread.sleep(60L);
    }catch(Exception e){
        e.printStackTrace();
    }
    System.out.println("Thread-A 线程运行结束后的状态 : "+tha.getState());
}

private synchronized void syncMethod(){
    System.out.println("----" + Thread.currentThread().getName() + " 线程获取到方法锁");
    try {
        Thread.sleep(50L);
    }catch(Exception e){
        e.printStackTrace();
    }
}

运行结果:

read-A 线程刚创建后的状态 : NEW
Thread-A 线程执行start方法后的状态 : RUNNABLE
----Thread-B 线程获取到方法锁
Thread-A 线程等待执行ayncMehtod时的状态 : BLOCKED
----Thread-A 线程获取到方法锁
Thread-A 线程执行asyncMehtod后线程等待50S时的状态 : TIMED_WAITING
Thread-A 线程运行结束后的状态 : TERMINATED

进程已结束,退出代码 0

线程状态分类图

图片[2]-线程的状态及转换-不念博客

线程状态转换

图片[3]-线程的状态及转换-不念博客

总结

通过以上的说明,样例及图示,我们对线程的状态种类、状态分类、状态的转换已经有了很清晰的认识。

同时,也比较明确,NEW和TERMINATED状态,在现实场景中,很难看到;

RUNNABLE状态的线程是会占用CPU资源的;

BLOCKED和TIMED_WAITING以及WAITING状态,均为阻塞状态,其中BLOCKED状态为资源锁等待,

TIMED_WAITING和WAITING为等待另一个线程执行结果的状态等待,他们均不占用CPU资源,但BLOCKED是会存在耗时及并发等待的。

© 版权声明
THE END