java建立執行緒的四種方法
第一種: 通過繼承Thread類建立執行緒
第二種: 通過實現Runnable介面建立執行緒
這兩種早已爛記於心,這裡就不作過多的介紹, 主要介紹其原始碼
Thread類 implements Runnable
thread空執行緒的run方法 是判斷target是否存在實,再執行target例項中的run方法
public void run(){ if(this.target != null){ this.target.run(); } }
通過實現Runnable介面, 並且通過thread建構函式建立執行緒的方法
Runnable runnable = newRunnable(){...重寫run方法}; Thread thread_one = new Thread(runnable); Thread thread_two = new Thread(runnable);
如果建立多個執行緒, 實質是多個執行緒引用同一個target 例項
對比兩種方式的區別:
通過繼承Thread類實現多執行緒的方式由於單繼承的侷限性, 不能再繼承其他類, 只能完成各自的任務
通過實現Runnable介面實現多執行緒的方式能更好的做到併發完成同一個任務, 因為訪問的是同一個target, 實現了共享資料
總之,在大多數情況下,都偏向於通過實現Runnable介面建立多執行緒
第三種: 使用Callable介面 和 FutureTask類建立執行緒
由於Thread類和Runnbale介面中的run方法沒有返回值, 所以這兩種方式不能獲取非同步執行的結果
Callable介面
package java.util.concurrent; @FunctionalInterface public interface Callable<V>{ V call() throws Exception; }
@FunctionalInterface 註解標註在介面上, 表示此介面為"函式式介面"
函式式介面: 只有一個抽象方法的介面
此註解只是方便編譯器進行檢查, 不加也不會影響. 如果加了註解但該介面不是函式式介面,編譯器會報錯
Callable介面是泛型介面 ,也是函式式介面
call()抽象方法還有一個Exception的異常宣告, 容許方法內的異常直接丟擲,並且可以不予捕獲
Future介面, RunnableFuture介面,以及FutureTask實現類都是位於 java.util.concurrent包下
V get() 用於阻塞性得到非同步執行的結果. 此方法是阻塞性的,非同步未執行完會處於阻塞狀態
Object outcome 用於儲存call()方法的非同步執行結果. get()會獲取
建立執行緒的具體步驟
class ReturnableTask implements Callable<Long>{ public long call() throws Exception{ //執行緒要執行的程式碼 } } public static void main(String args[]) throws InterruptedException{ ReturnableTask task = new new ReturnableTask(); Futuretask<Long> FutureTask = new Futuretask<Long>(task); Thread thread = new Thread(FutureTask,"returnableThread"); thread.start(); System.out.println(FutureTask.get()); //得到非同步執行結果 }
下圖為具體實現過程
兩個執行緒處於併發狀態, 預設非同步執行
看起來兩個執行緒是同時進行,實質上是不是, 單個程序在同一時間只能執行一個程序,由於分給執行緒的時間片非常短(執行緒切換毫秒級),所以以為是同時
併發執行的訊息通訊機制分為同步和非同步, 這些就不做過多解釋
總之,圖上的兩個執行緒不是同時執行
第四種: 通過執行緒池建立執行緒
通過Thread建立執行緒在執行完就被銷燬了, 不可服用. 在高併發場景中, 頻繁建立執行緒是非常消耗資源的, 通過執行緒池建立執行緒可以對已經建立好的執行緒進行復用
Executors 靜態工廠類 用於建立不同的執行緒池 java.util.concurrent;
//建立一個包含三個執行緒的執行緒池 private static ExecutorService pool = Executors.newFixedThreadPool(3);
Executor介面
void executo(Runnable command); //執行Runnable型別
ExecutorService<T> extends Executor
<T> Future<T> submit(Callable<T> task) //提交callable型別以執行
Future<?> submit(Runnable task) //提交Runnable型別以執行
具體實現
main Future future = pool.submit(new RuturnableTask()); Long result = (Long) future.get(); //得到非同步執行的結果
execute() 與 submit() 執行執行緒方法的區別
execute()只能執行Runnable, 並且無返回值
submit() 既能執行Runnable又能執行callable, 並且有返回值
注: 實際生產環境中禁止使用Executors建立執行緒池