Java并发基础学习(三)——线程生命周期

前言

上一篇博客介绍了线程如何正确停止,这一篇博客开始介绍线程的生命周期,也是面试中常说的线程的几种状态,同时针对这几种状态的转换我们做一个总结。

哪几种状态

关于线程到底有哪几种状态,看过一些总结,实在是太杂了,说啥的都有。甚至有些博客文章中总结图里头,状态的名称都不一样。其实在Thread类的源码中,针对线程有几种状态,都一一定义了对应的枚举类型,具体如下,可以根据这个总结出Java中线程的几种状态

public enum State {
    
    
    /**
     * Thread state for a thread which has not yet started.
     */
    NEW,

    /**
     * Thread state for a runnable thread.  A thread in the runnable
     * state is executing in the Java virtual machine but it may
     * be waiting for other resources from the operating system
     * such as processor.
     */
    RUNNABLE,

    /**
     * Thread state for a thread blocked waiting for a monitor lock.
     * A thread in the blocked state is waiting for a monitor lock
     * to enter a synchronized block/method or
     * reenter a synchronized block/method after calling
     * {@link Object#wait() Object.wait}.
     */
    BLOCKED,

    /**
     * Thread state for a waiting thread.
     * A thread is in the waiting state due to calling one of the
     * following methods:
     * <ul>
     *   <li>{@link Object#wait() Object.wait} with no timeout</li>
     *   <li>{@link #join() Thread.join} with no timeout</li>
     *   <li>{@link LockSupport#park() LockSupport.park}</li>
     * </ul>
     *
     * <p>A thread in the waiting state is waiting for another thread to
     * perform a particular action.
     *
     * For example, a thread that has called <tt>Object.wait()</tt>
     * on an object is waiting for another thread to call
     * <tt>Object.notify()</tt> or <tt>Object.notifyAll()</tt> on
     * that object. A thread that has called <tt>Thread.join()</tt>
     * is waiting for a specified thread to terminate.
     */
    WAITING,

    /**
     * Thread state for a waiting thread with a specified waiting time.
     * A thread is in the timed waiting state due to calling one of
     * the following methods with a specified positive waiting time:
     * <ul>
     *   <li>{@link #sleep Thread.sleep}</li>
     *   <li>{@link Object#wait(long) Object.wait} with timeout</li>
     *   <li>{@link #join(long) Thread.join} with timeout</li>
     *   <li>{@link LockSupport#parkNanos LockSupport.parkNanos}</li>
     *   <li>{@link LockSupport#parkUntil LockSupport.parkUntil}</li>
     * </ul>
     */
    TIMED_WAITING,

    /**
     * Thread state for a terminated thread.
     * The thread has completed execution.
     */
    TERMINATED;
}

权威的结论——Java线程存在6种状态

状态 具体含义
NEW 对应的线程对象只是New出来了,还没有调用start方法
RUNNABLE 正在执行的,或者在等待CPU调度执行的线程,都为Runnable的状态
BLOCKED 当一个线程想进入到synchronize修饰的代码块,但是无法获取锁的时候的状态,即为BLOCKED状态 (BLOCKED的状态特指进入synchronize时阻塞的状态)
WAITING 因为调用Object.wait(),Thread.join(),LockSupport.park()之后,线程进入的阻塞状态,这个时候线程等待其他线程唤醒
TIMED_WAITING 因为调用sleep(),Object.wait(long),join(long),LockSupport.parkNanos,LockSupport.parkUntil等方法进入到的计时等待状态,时间到了之后,线程自动被唤醒
TERMINATED 线程的终止状态,线程运行完毕会进入到该状态

需要说明的是,Java中的线程状态只有这6种,没有其他的相关说法。

状态转换图

在上面的基础上,我们再绘制线程的状态转换图

请添加图片描述

相关代码实例

关于NEW、Runnable、Terminated状态的实例

/**
 * autor:liman
 * createtime:2021/9/11
 * comment:展示线程的new runnable terminated状态
 */
@Slf4j
public class NewRunnableTerminated implements Runnable {
    
    

    @Override
    public void run() {
    
    
        for (int i = 0; i < 10000; i++) {
    
    
            System.out.println(i);
        }
        System.out.println(Thread.currentThread().getState());
    }

    public static void main(String[] args) throws InterruptedException {
    
    
        Thread thread = new Thread(new NewRunnableTerminated());
        System.out.println(thread.getState());//NEW
        thread.start();
        System.out.println(thread.getState());//刚开始,不一定有资源,也是RUNNABLE
        Thread.sleep(5);
        System.out.println(thread.getState());//打印线程正在运行的状态也是RUNNABLE
        Thread.sleep(10);
        System.out.println(thread.getState());//TERMINATED
    }

}

之前很多资料上还介绍过,线程运行中和等待运行不是一个状态,上面的实例来看并不是这样。

关于BLOCKED、WAITING、TIME_WAITING三个状态的实例

/**
 * autor:liman
 * createtime:2021/9/11
 * comment:演示线程 blocked waiting TimeWaiting的三种状态
 */
@Slf4j
public class BlockedWaitingTimedWaiting implements Runnable{
    
    
    @Override
    public void run() {
    
    
        sync();
    }

    private synchronized void sync(){
    
    
        try {
    
    
            Thread.sleep(1000);//sleep的状态是一种TIMED_WAITING的状态
            wait();//线程执行完sleep,就会进入到wait状态
        } catch (InterruptedException e) {
    
    //虽然不应该在子方法中处理中断异常,但为了演示,这里就随意了
            e.printStackTrace();
        }
    }

    public static void main(String[] args) {
    
    
        BlockedWaitingTimedWaiting runnable = new BlockedWaitingTimedWaiting();
        Thread thread1 = new Thread(runnable);
        thread1.start();
        Thread thread2 = new Thread(runnable);
        thread2.start();
        try {
    
    
            //主线程暂停一下,以便拿到线程最新的状态
            Thread.sleep(50);
        } catch (InterruptedException e) {
    
    
            e.printStackTrace();
        }
        //打印出TIME_WAITING,因为线程1正在sleep
        log.info("线程1当前的状态为:{}",thread1.getState());
        //线程2想拿到sync的锁,但是拿不到,这里线程2就是BLOCKED状态
        log.info("线程2当前的状态为:{}",thread2.getState());
        try {
    
    
            //主线程暂停一下,以便线程1进入到wait状态线程最新的状态
            Thread.sleep(1300);
        } catch (InterruptedException e) {
    
    
            e.printStackTrace();
        }
        //由于调用了wait方法,这里线程1就是wait状态
        log.info("线程1当前的状态为:{}",thread1.getState());
    }
}

运行结果如下:

请添加图片描述

一些面试题

1、线程有哪几种状态(线程的生命周期是什么)

6种,对应图来回答即可,需要注意的是并不存在什么所谓的Running状态。

2、阻塞只是指的BLOCKED么?

不仅仅是BLOCKED状态,一般情况下,BLOCKED状态,WAITING状态,TIME_WAITING状态都称为阻塞状态

总结

简单总结了一下线程的几种状态,下一个小结会总结Thread类中的一些方法,比如wait和join等。

猜你喜欢

转载自blog.csdn.net/liman65727/article/details/120687342