start()方法原理解读

1,694 阅读2分钟

start()方法原理解读

1 方法含义

1.1 启动新线程

1.start()方法调用后,并不意味着该线程立马运行,只是通知JVM在一个合适的时间运行该线程。 有可能很长时间都不会运行,比如遇到饥饿的情况。
2.调用start()党发的顺序并不能决定线程执行的顺序。
3.start()方法其实会让两个线程运行。第一个就是我们主线程,因为我们必须要有一个线程,哪怕不是主线程,来执行start()方法。第二个才是刚刚创建的子线程。
4.不要误以为 new Thread().start()这行代码就是新创建的子线程执行的,这行语句其实父线程或者说我们的主线程来执行的。这行语句这我们的父线程或主线程执行之后,才去创建了新线程。

1.2 准备工作

首先会让自己处于就绪状态。就绪状态指的是,我已经获取到除了CPU以外的其他资源。比如该线程已经设置了上下文,栈,线程状态,以及PC, 做完准备工作后,线程才可以被JVM或者操作系统进一步调度到执行状态。调度到执行状态后,等待获取CPU资源,然后才会进入到运行状态,执行run()方法里面的代码。

1.3 不能重复地执行start()方法

package startthread;

public class CannotStartTwice {

    public static void main(String[] args) {
        Thread thread = new Thread();
        thread.start();
        thread.start();
    }

}

出现如下异常:java.lang.IllegalThreadStateException

重复执行start()异常

2.源码分析

2.1 启动新线程检查线程状态

public synchronized void start() {
        /**
         * This method is not invoked for the main method thread or "system"
         * group threads created/set up by the VM. Any new functionality added
         * to this method in the future may have to also be added to the VM.
         *
         * A zero status value corresponds to state "NEW".
         */
        if (threadStatus != 0)
            throw new IllegalThreadStateException();

        /* Notify the group that this thread is about to be started
         * so that it can be added to the group's list of threads
         * and the group's unstarted count can be decremented. */
        group.add(this); //加入到一个线程组

        boolean started = false;
        try {
            start0();
            started = true;
        } finally {
            try {
                if (!started) {
                    group.threadStartFailed(this);
                }
            } catch (Throwable ignore) {
                /* do nothing. If start0 threw a Throwable then
                  it will be passed up the call stack */
            }
        }
    }

主要由于该方法:

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

而threadStatus初始化就是0,private volatile int threadStatus = 0;

2.2 加入线程组

2.3 调用start0()

start方法流程

3.深入JDK源码