昨天棧長介紹了《Java多線程可以分組,還能這樣玩!》線程分組的妙用。今天,棧長會詳細介紹 Java 中的多線程 start() 和 run() 兩個方法,Java 老司機請跳過,新手或者對這兩個不是很了解的可以繼續往下看。
首先要知道實作多線程最基本的兩種方式:
1、繼承
java.lang.Thread
類;
2、實作
java.lang.Runnable
接口;
其中 Thread 類也是實作了 Runnable 接口,而 Runnable 接口定義了唯一的一個 run() 方法,是以基于 Thread 和 Runnable 建立多線程都需要實作 run() 方法,是多線程真正運作的主方法。
@FunctionalInterface
public interface Runnable {
public abstract void run();
}
而 start() 方法則是 Thread 類的方法,用來異步啟動一個線程,然後主線程立刻傳回。該啟動的線程不會馬上運作,會放到等待隊列中等待 CPU 排程,隻有線程真正被 CPU 排程時才會調用 run() 方法執行。
是以 start() 方法隻是辨別線程為就緒狀态的一個附加方法,以下 start() 方法的源碼,其中 start0() 是一個本地 native 方法。
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) {
/* do nothing. If start0 threw a Throwable then
it will be passed up the call stack */
}
}
}
請注意,start() 方法被辨別為 synchronized 的,即為了防止被多次啟動的一個同步操作。
那麼你會問了,為什麼要有兩個方法,直接用一個 run() 方法不就行了嗎!? 還真不行,如果直接調用 run() 方法,那就等于調用了一個普通的同步方法,達不到多線程運作的異步執行,來看下面的例子。
/**
* 微信公衆号:Java技術棧
*/
public static void main(String[] args) {
Thread thread = new Thread(() -> {
try {
Thread.sleep(3000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("Java技術棧");
});
long start = System.currentTimeMillis();
thread.start();
System.out.println(System.currentTimeMillis() - start);
start = System.currentTimeMillis();
thread.run();
System.out.println(System.currentTimeMillis() - start);
}
程式輸出:
0
Java技術棧
3000
Java技術棧
從程式輸出結果可以看出,啟動 start 方法前後隻用了 0 毫秒,而啟動 run 方法則阻塞了 3000 毫秒等程式執行完再繼續執行,這就是同步與異步的一個最重要的差別。
看完這篇,你應該對 start 和 run 方法有了一個大概的掌握吧,再也不怕面試官問你這兩個的差別了吧!