并发与多线程(三)--验证线程的生命的生命周期/状态

本文深入探讨了线程的生命周期及其状态转换,纠正了线程运行时状态为Runnable而非Running的常见误解,并通过代码验证了线程在不同场景下的状态表现。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

线程的生命周期或者说状态其实不复杂,但是很多人的理解可能有错误,一个典型的误区,线程运行时的状态是Runnable,而不是Running,因为线程没有Running状态。

线程的状态

1、New:已创建,没启动。还没有执行start()

2、Runnable:调用start()之后就处于Runnable,无论是否已经运行,都是Runnable状态,对应操作系统的Ready和Running状态。

3、Blocked:进入Synchronized修饰的方法或者代码块,但是无法获取锁,就处于Blocked。

4、Waiting:线程进入等待的阻塞状态,例如调用Object.wait()。

5、Timed-Waiting:线程进入计时等待的阻塞状态,例如调用Thread.sleep(time)。

6、Terminated:线程执行代码结束,或者出现未捕捉的异常。

PS:线程没有Running状态的证明,请参考官方文档:官方文档

线程的状态转换

image
从上图,可以明确看到状态如何进行转换,状态之间的变化是否可逆。。。

其实,从Waiting到Blocked状态可以可以的,当Waiting状态被唤醒之后,如果暂时没有获取到monitor锁,这时候就会进入Blocked状态,当获取锁之后,重新变成Runnable。Waiting和Timed-Waiting状态下在出现未捕获异常时,就会直接进入Terminated。

PS:Waiting和Timed-Waiting状态下通过interrupt()响应中断,会进入Runnable状态。

验证线程状态

为了上面所讲线程状态的可信度,我们通过代码进行验证

1、New、Runnable、Terminated

public static void main(String[] args) throws InterruptedException{
    Thread thread = new Thread(() -> {
        for (int i = 0; i <= 4; i++) {
            log.info("{}", i);
            if (i == 2) {
                log.info("子线程运行过程中状态:{}", Thread.currentThread().getState());
            }
        }
    });

    log.info("子线程没有执行start时,状态:{}", thread.getState());
    thread.start();
    log.info("子线程执行start后,状态:{}", thread.getState());
    Thread.sleep(10);
    log.info("子线程执行结束,状态:{}", thread.getState());
}
结果:
17:12:11.244 [main] INFO com.diamondshine.Thread.ThreadClass - 子线程没有执行start时,状态:NEW
17:12:11.251 [main] INFO com.diamondshine.Thread.ThreadClass - 子线程执行start后,状态:RUNNABLE
17:12:11.251 [Thread-0] INFO com.diamondshine.Thread.ThreadClass - 0
17:12:11.251 [Thread-0] INFO com.diamondshine.Thread.ThreadClass - 1
17:12:11.251 [Thread-0] INFO com.diamondshine.Thread.ThreadClass - 2
17:12:11.252 [Thread-0] INFO com.diamondshine.Thread.ThreadClass - 子线程运行过程中状态:RUNNABLE
17:12:11.252 [Thread-0] INFO com.diamondshine.Thread.ThreadClass - 3
17:12:11.252 [Thread-0] INFO com.diamondshine.Thread.ThreadClass - 4
17:12:11.262 [main] INFO com.diamondshine.Thread.ThreadClass - 子线程执行结束,状态:TERMINATED

成功验证了在子线程执行过程中的状态是Runnable,而不是Running。

2、Blocked、Waiting、Time-Waiting

@Slf4j
public class ThreadClass implements Runnable{

    public static void main(String[] args) throws InterruptedException{

        ThreadClass threadClass = new ThreadClass();
        Thread thread = new Thread(threadClass);
        thread.start();
        Thread thread1 = new Thread(threadClass);
        thread1.start();

        //sleep 5ms为了让子线程执行到synchronize()的Thread.sleep(1000)
        try {
            Thread.sleep(5);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

        log.info("第一个线程的状态:{}", thread.getState());
        //此时第一个线程获取monitor锁,然后休眠1000ms,所以第二个线程无法获得锁
        log.info("第二个线程的状态:{}", thread1.getState());

        //休眠1100ms为了让代码执行到wait();
        Thread.sleep(1100);
        log.info("第一个线程的状态:{}", thread.getState());
    }

    @Override
    public void run() {
        synchronize();
    }

    private synchronized void synchronize() {
        try {
            Thread.sleep(1000);
            wait();
        } catch (InterruptedException e) {
            Thread.currentThread().interrupt();
            e.printStackTrace();
        }
    }
}
结果:
17:46:19.601 [main] INFO com.diamondshine.Thread.ThreadClass - 第一个线程的状态:TIMED_WAITING
17:46:19.608 [main] INFO com.diamondshine.Thread.ThreadClass - 第二个线程的状态:BLOCKED
17:46:20.708 [main] INFO com.diamondshine.Thread.ThreadClass - 第一个线程的状态:WAITING

验证结果符合预期,当调用sleep(),线程处于Timed_Waiting,因为Synchronized进入阻塞,处于Blocked,调用wait(),处于waiting状态。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值