昨天棧長介紹了《Java多線程能夠分組,還能這樣玩!》線程分組的妙用。今天,棧長會詳細介紹 Java 中的多線程 start() 和 run() 兩個方法,Java 老司機請跳過,新手或者對這兩個不是很理解的能夠繼續往下看。java
首先要知道實現多線程最基本的兩種方式:面試
一、繼承 java.lang.Thread
類;多線程
二、實現 java.lang.Runnable
接口;異步
其中 Thread 類也是實現了 Runnable 接口,而 Runnable 接口定義了惟一的一個 run() 方法,因此基於 Thread 和 Runnable 建立多線程都須要實現 run() 方法,是多線程真正運行的主方法。this
@FunctionalInterface public interface Runnable { public abstract void run(); }
而 start() 方法則是 Thread 類的方法,用來異步啓動一個線程,而後主線程馬上返回。該啓動的線程不會立刻運行,會放到等待隊列中等待 CPU 調度,只有線程真正被 CPU 調度時纔會調用 run() 方法執行。線程
因此 start() 方法只是標識線程爲就緒狀態的一個附加方法,如下 start() 方法的源碼,其中 start0() 是一個本地 native 方法。code
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 方法有了一個大概的掌握吧,不再怕面試官問你這兩個的區別了吧!
動手轉發給更多的朋友吧!
更多 Java 多線程技術文章請在Java技術棧公衆號後臺回覆關鍵字:多線程。
本文原創首發於公衆號:Java技術棧(id:javastack),關注公衆號在後臺回覆 "多線程" 可獲取更多,轉載請原樣保留本信息。