启动线程

对比start方法与run方法

代码部分

public class StartAndRunMethod {
    public static void main(String[] args) {
        Runnable printThreadName=()->{
            System.out.println(Thread.currentThread().getName());
        };
        new Thread(printThreadName).run();//result:main
        new Thread(printThreadName).start();//Thread-0
    }
}

正确启动一个线程的方法应该是使用start方法。
对比start方法与run方法的源码,如下所示。

  1. run
    /**
     * If this thread was constructed using a separate
     * <code>Runnable</code> run object, then that
     * <code>Runnable</code> object's <code>run</code> method is called;
     * otherwise, this method does nothing and returns.
     * <p>
     * Subclasses of <code>Thread</code> should override this method.
     *
     * @see     #start()
     * @see     #stop()
     * @see     #Thread(ThreadGroup, Runnable, String)
     */
    @Override
    public void run() {
        if (target != null) {
            target.run();
        }
    }
  1. start
    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 */
            }
        }
    }

start方法主要关注try代码块中的代码。从上可以看到如果是执行run方法的话,那么就是主线程直接执行了那段代码块,调用了target的run方法,所以结果肯定是Main。而start方法里面有一个关键函数调用start0,这一句是用来创建线程的,也就是说必须要先创建线程才行,所以必须要用start方法。
调用了start方法不一定就立刻会创建线程,这得根据JVM的调度算法来决定。

  • 不能重复调用start,否则会抛出异常java.lang.IllegalThreadStateException。
    再次阅读start方法的代码,可以看到start方法分为了三步:
    1. 检查线程状态
    2. 加入线程组
    3. 启动线程
      在第一步中,如果线程状态不为0(线程状态为NEW)的话就会抛出java.lang.IllegalThreadStateException。
      另外start方法是被synchronized关键字修饰的,可以保证线程安全,main方法线程和system组的线程则是由JVM创建的,并不会通过start来启动。
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。