問題
Java 線程調(diào)用start()后會立即執(zhí)行run()方法嗎?
我們在開發(fā)中顿天,經(jīng)常和線程打交道泄朴,有些東西總是司空見慣,想當然地認為某些事情理所當然...
但是今天偶然發(fā)現(xiàn)一個有趣的現(xiàn)象:
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()--");
}
}
運行結(jié)果如下:
看到運行結(jié)果之后露氮,我愣了一下祖灰,WTF?
跟我想的有點不一樣啊,
理論上來講畔规,線程調(diào)用start()之后局扶,將會調(diào)用該線程的run();
我又趕緊去查看了Java的官方文檔:JavaAPI
Cause this thread to begin execution ; the Java Virtual Machine calls the run method of this thread.
通過上面我們可以發(fā)現(xiàn)start()就是使該線程開始運行,JVM會調(diào)用線程的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);
關鍵代碼已經(jīng)貼出,但是似乎關鍵在于nativeCreate()方法莫绣。該方法屬于c方法畴蒲,有時間再追蹤一下。
思考
通過代碼測試我們發(fā)現(xiàn)線程調(diào)用start()方法对室,并不會立刻執(zhí)行run()方法模燥。但是兩者之間的時間差是多少呢?
測試用例,有興趣的朋友can have a try.
把運行結(jié)果給出來:
通過我的多次測試掩宜,run()和start()的時間差一般都在[0,8]之內(nèi)蔫骂,當然運行足夠多次會發(fā)現(xiàn)時間差會更大。
總結(jié)
雖然該用例看似沒什么卵用牺汤,但不親自上手嘗試辽旋,還真會回答錯...有趣有趣...
需要注意的是如果我們在線程中創(chuàng)建對象,而在start()方法后直接使用該對象檐迟,就會出現(xiàn)該問題測試用例补胚。
夫小惑易方,大惑易性...