Java 线程调用start()后会立即执行run()方法吗?

别想当然

问题

Java 线程调用start()后会立即执行run()方法吗?

我们在开发中,经常和线程打交道,有些东西总是司空见惯,想当然地认为某些事情理所当然...
但是今天偶然发现一个有趣的现象:

class Test {
    public static void main(String[] args) {
        System.out.println("hello https://tool.lu/");

        Runnable runnable = new Runnable(){
            @Override
                public void run() {
                System.out.println("--run()--");
            }
        };

        Thread thread = new Thread(runnable);
        thread.start();
        System.out.println("--after start()--");
    }
}


运行结果如下:


运行结果

看到运行结果之后,我愣了一下,WTF?
跟我想的有点不一样啊,

理论上来讲,线程调用start()之后,将会调用该线程的run();
我又赶紧去查看了Java的官方文档:JavaAPI

Thread的start()

Cause this thread to begin execution ; the Java Virtual Machine calls the run method of this thread.

通过上面我们可以发现start()就是使该线程开始运行,JVM会调用线程的run()方法。

那我们只能从源码中找答案啦。

  /**
     * Causes this thread to begin execution; the Java Virtual Machine
     * calls the <code>run</code> method of this thread.
     * <p>
     * The result is that two threads are running concurrently: the
     * current thread (which returns from the call to the
     * <code>start</code> method) and the other thread (which executes its
     * <code>run</code> method).
     * <p>
     * It is never legal to start a thread more than once.
     * In particular, a thread may not be restarted once it has completed
     * execution.
     *
     * @exception  IllegalThreadStateException  if the thread was already
     *               started.
     * @see        #run()
     * @see        #stop()
     */
    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".
         */
        // Android-changed: throw if 'started' is true
        if (threadStatus != 0 || started)
            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);

        started = false;
        try {
            nativeCreate(this, stackSize, daemon);
            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 */
            }
        }
    }

    private native static void nativeCreate(Thread t, long stackSize, boolean daemon);

关键代码已经贴出,但是似乎关键在于nativeCreate()方法。该方法属于c方法,有时间再追踪一下。

思考

通过代码测试我们发现线程调用start()方法,并不会立刻执行run()方法。但是两者之间的时间差是多少呢?

测试用例,有兴趣的朋友can have a try.

把运行结果给出来:


运行结果

通过我的多次测试,run()和start()的时间差一般都在[0,8]之内,当然运行足够多次会发现时间差会更大。

总结

虽然该用例看似没什么卵用,但不亲自上手尝试,还真会回答错...有趣有趣...
需要注意的是如果我们在线程中创建对象,而在start()方法后直接使用该对象,就会出现该问题测试用例


夫小惑易方,大惑易性...

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容

  • 1. Java基础部分 基础部分的顺序:基本语法,类相关的语法,内部类的语法,继承相关的语法,异常的语法,线程的语...
    子非鱼_t_阅读 31,954评论 18 399
  • 文章来源:http://www.54tianzhisheng.cn/2017/06/04/Java-Thread/...
    beneke阅读 5,455评论 0 1
  • 本文主要讲了java中多线程的使用方法、线程同步、线程数据传递、线程状态及相应的一些线程函数用法、概述等。 首先讲...
    李欣阳阅读 7,190评论 1 15
  • Java多线程学习 [-] 一扩展javalangThread类 二实现javalangRunnable接口 三T...
    影驰阅读 8,072评论 1 18
  • 1 2014年3月傍晚。我在龙门大排档和狐朋狗友撸串,吃的正嗨,公司一通电话打来,让我立即、马上、火速赶到火车站!...
    莫愁塘主阅读 3,875评论 15 27