執行緒池的實現核心之一是futuretask。在提交任務時,使用者實現的callable例項task會被包裝為futuretask例項ftask;提交後任務非同步執行,無需使用者關心;當使用者需要時,再呼叫futuretask#get()獲取結果——或異常。方法中可能會呼叫到多個服務/方法,且這些服務/方法之間是互相獨立的,不存在先後關係。在高併發場景下,如果執行比較耗時,可以考慮多執行緒非同步的方式呼叫。
乙個150ms,乙個200ms:
public class userapi catch (interruptedexception e)
return userinfo;
}/** 查詢使用者位址,模擬耗時200ms */
public string queryuseraddress(long userid) catch (interruptedexception e)
return useraddress;
}}
@test
public void testnotusefuturetask()
執行幾次,結果:
testnotusefuturetask 耗時:358
testnotusefuturetask 耗時:360
從結果中,可以看到,總耗時是大於queryuserinfo
和queryuseraddress
之和的。但這兩個服務邏輯上並不存在先後關係,理論上最長耗時取決於最慢的那個,即queryuseraddress
下例使用了futuretask
,來非同步呼叫queryuserinfo
和queryuseraddress
。
@test
public void testusefuturetask() throws executionexception, interruptedexception
};callableuseraddresscallable = new callable()
};futuretaskuserinfofuturetask = new futuretask<>(userinfocallable);
futuretaskuseraddressfuturetask = new futuretask<>(useraddresscallable);
new thread(userinfofuturetask).start();
new thread(useraddressfuturetask).start();
string userinfo = userinfofuturetask.get();
string useraddress = useraddressfuturetask.get();
system.err.println("testusefuturetask 耗時:" + (system.currenttimemillis() - starttime));
}
執行幾次,結果:
testusefuturetask 耗時:239
testusefuturetask 耗時:237
很明顯,總耗時大大減少了,這就驗證了前面所說,總耗時取決於queryuseraddress
的耗時。
從前面使用futuretask的**中可以看到,乙個futuretask需要包含以下幾點:
1、范型
2、建構函式,傳入callable
3、實現runnable
4、有返回值
public class myfuturetaskimplements runnable
@override
public void run() catch (exception e)
state = "done";
synchronized (this)
}/** 獲取呼叫結果 */
public t get() throws interruptedexception
synchronized (this)
return result;
}}
@test
public void testmyusefuturetask() throws interruptedexception
};callableuseraddresscallable = new callable()
};// 不同點
myfuturetaskuserinfofuturetask = new myfuturetask<>(userinfocallable);
myfuturetaskuseraddressfuturetask = new myfuturetask<>(useraddresscallable);
new thread(userinfofuturetask).start();
new thread(useraddressfuturetask).start();
string userinfo = userinfofuturetask.get();
string useraddress = useraddressfuturetask.get();
system.err.println("testmyusefuturetask 耗時:" + (system.currenttimemillis() - starttime));
}
testmyusefuturetask 耗時:208
testmyusefuturetask 耗時:211
從結果中看到,預期與使用futuretask
的一致。至於使用我們自定義的myfuturetask
執行耗時為何會比futuretask
長,我猜測是我們自己寫的未做更多的檢查和判斷。我們自己寫的只是用來學習futuretask
。
不使用非同步的方式時,queryuseraddress
在queryuserinfo
執行之後才會執行,兩者相加的時間算入總呼叫耗時。如果使用了非同步執行緒呼叫,由於queryuseraddress
耗時長,這樣在queryuseraddress
執行結束前,queryuserinfo
就執行結束了,這樣queryuserinfo
呼叫耗時就不計了。
FutureTask基本用法
1.futuretask獲取非同步執行的資料 場景 非同步執行10次1 99的計算結果,然後再執行主業務邏輯,最後獲取每次執行的結果,再把10次的計算結果相加 public static void main string args throws interruptedexception,execut...
FutureTask 原始碼閱讀
public void run catch throwable ex if ran set result finally get操作的核心方法 private intawaitdone boolean timed,long nanos throws interruptedexception int ...
多執行緒之 FutureTask
兩種使用場景 1.非同步任務 主線程繼續執行,當主線程需要非同步執行緒的結果時,直接去調非同步執行緒就可以 注意一點 對於多執行緒共享的物件,採用volatile unsafe的方法,代替鎖操作,這個是很重要的一點操作 獲取任務的執行結果用乙個集合儲存 public class futuretask...