好好谈谈线程的生命周期打完收工,源码地址

在我们开始本文话题时,我们不妨复习以下(或者说学习一下)操作系统的生命周期。

图片.png

1.初始状态,这时候仅仅是语言层面上的线程创建,在操作系统中并没有创建这样一个线程:
2.当进入可运行状态时,说明该线程允许已被创建且一切准备就绪,随时可以进入运行状态了。
3.运行状态则以为着当前线程已分配到cpu时间片,执行自己所需要完成的工作了。
4.休眠状态,说明该线程正处于一个调用某个阻塞api或者等待某个事件完成的情况,这时候他就会适当cpu的使用权,进入休眠状态,直到等待事件出现后线程才会处于可运行状态。
5.终止状态:当线程完成了所有工作或者出现异常,那么线程最终就会走向人生的终点。
复制代码

图片.png

好了,讲完操作系统的线程状态,我们基于java源码看看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个状态,实际上翻译翻译就是操作系统拿到四种状态,如下图所示

图片.png

可以看出笔者的归纳方式很简单,线程的初始状态和java线程的new一样的不多说,而操作系统的可运行和运行心态则是对应java的RUNNABLE是为什么呢?

我们从上面state源码注释就了解到,RUNNABLE状态即该线程已经在jvm中运行,但可能还在等待其他资源操作它,例如处理器。这句话的意思也很明显,我们可以用《java并发编程的实战》的一句话进行解释

    在jvm层面看来,操作系统等待cpu使用权(可运行状态)以及等IO(休眠状态)都是属于等待某个资源操作,所以都归入RUNNABLE。
复制代码

对于操作系统对应休眠状态,由于jvm层面导致线程休眠的方式很多,所以在状态上也比操作系统多,下面我们就可以通过一张图来解释,为什么jvm层面会有这么多的休眠状态。

图片.png

相信你们已经看完了这张图,那么我们就用几个示例来演示线程状态的切换

首先是new状态

/**
 * 线程的new状态场景
 */
public static void newState() {
    Thread thread = new Thread(() -> {
    });
    System.out.println(thread.getState());
}
复制代码

RUNNABLE与BLOCKED状态转换

/**
 * 线程出现block的场景
 *
 * @throws Exception
 */
public static void blockState() throws Exception {
    Thread t1 = new Thread(new BlockThread());
    Thread t2 = new Thread(new BlockThread());
    t1.start();
    //当t2等待t1释放synchronized内置锁时就会处于block状态
    t2.start();
    Thread.sleep(1000);

    System.out.println(t2.getState());
    System.exit(0);
}
复制代码
public class BlockThread implements Runnable {
    
    @Override
    public void run() {
        loop();
    }

    /**
     * 拿着synchronized内置锁死循环
     */
    public static synchronized void loop() {
        while (true) {

        }
    }
}
复制代码

RUNNABLE与WAITING状态转换,根据上图说明调用join即可进入waiting

 public static void waitingState() throws Exception {

        Thread t1 = Thread.currentThread();
        Thread t2 = new Thread(() -> {
            try {
//                主线程休眠
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                Thread.currentThread().interrupt();
                System.out.println("线程休眠失败,失败原因 " + e);
            }
//            t2运行 那么t1就得等着
            System.out.println(t1.getState());
        });
        t2.start();
        t2.join();
    }
复制代码

调⽤了 sleep(long) 等⽅法,线程从 RUNNABLE 变为 TIMED-WAITING 状态

public static void  timeWaitingState()throws Exception{
    Thread t=new Thread(()->{
        try {
            //让主线程进入等待状态,自己也得等着主线程睡完
            Thread.sleep(3000);
        } catch (InterruptedException e) {
            Thread.currentThread().interrupt();
            System.out.println("线程休眠失败,失败原因 " + e);
        }
    });
    t.start();
    Thread.sleep(1000);
    System.out.println(t.getState());
}
复制代码

线程执⾏完⾃然就到了 TERMINATED 状态了

public static void terminatedState()throws Exception{
    Thread thread=new Thread(()->{});
    thread.start();
    //子线程直接执行完 进入terminated
    Thread.sleep(1000);
    System.out.println(thread.getState());
}
复制代码

打完收工,源码地址

gitee.com/fugongliude…