JUC源码讲解:逐步解析 Thread.start() 源码

JUC源码讲解:逐步解析 Thread.start() 源码

抛出问题

当 new Thread() 时,线程会进入 NEW 状态,如果我们想要使用线程,就需要调用 start() 方法,那么,在使用 star() 时发生了什么?有什么需要注意的?线程是怎么一步步被创建的?跟着我一起分析源码吧!

阅读源码

为了方便讲解,我先把源码贴出来,然后逐步讲解每一步的作用

public synchronized void start() {

    if (threadStatus != 0)
        throw new IllegalThreadStateException();

    group.add(this);

    boolean started = false;
    try {
        start0();
        started = true;
    } finally {
        try {
            if (!started) {
                group.threadStartFailed(this);
            }
        } catch (Throwable ignore) {
            
        }
    }
}

我们先看这个方法头部分:

public synchronized void start() {
    if (threadStatus != 0)
        throw new IllegalThreadStateException();
}

注意到了吧,是 sync!这是为了避免被多个线程同时启动!

这个if判断,如果线程状态是 NEW,threadStatus 才等于 0,其他状态的线程是不能被 star() 的,否则会抛出线程状态异常,if 是为了避免线程被重复 start

这里提一下,init后的线程状态是NEW

看下一段,加入 ThreadGroup

group.add(this);

最后一段值得一提:

boolean started = false;
try {
    start0();
    started = true;
} finally {
    try {
        if (!started) {
            group.threadStartFailed(this);
        }
    } catch (Throwable ignore) {

    }
}

变量 started 是线程的启动状态,注意到 try 块中的 start0() 方法了吗?这是个 native 方法,目的是启动线程,在 start0() 彻底结束之前,线程的状态都是 READY!执行成功后,只要线程拿到了CPU执行权,就是 RUNNING状态

在 finally 中,通过 started 判断 start0() 是否执行成功,如果没有成功,会调用 group.threadStartFailed(this); 我们点进去这个方法里看一下吧

void threadStartFailed(Thread t) {
    synchronized(this) {
        remove(t);	// 删除该线程
        nUnstartedThreads++; // start 失败的计数器
    }
}

总结

  • start() 时为了避免线程被多次 start 而使用了 sync 和 if 。if保证非NEW状态的线程是不能被 start 的。sync方法保证不会被多个线程同时 start

  • 在 start0() 执行完全成功之前,线程的状态是 READY,执行成功后,如果线程拿到了CPU执行权,状态会变为 RUNNING,他们都是 Thread.State.class 中的 RUNNABLE 状态

  • start 失败会将线程删除,并报错给父线程

posted @ 2024-03-12 21:43  yangruomao  阅读(13)  评论(1编辑  收藏  举报