java核心-多線程-線程類-Callable、Future和FutureTask
阿新 • • 發佈:2019-04-28
包裝 示例 概念 return time let thread .sh int
基本概念
<1>Callable,Callable和Runnable差不多,兩者都是為那些其實例可能被另一個線程執行的類而設計的,最主要的差別在於Runnable不會
返回線程運算結果,Callable可以(假如線程需要返回運行結果)。
<2>Future,是一個接口表示異步計算的結果,它提供了檢查計算是否完成的方法,以等待計算的完成,並獲取計算的結果。
<3>FutureTask是Future的實現類,也可以說是進階類,優化了Future的一些缺點,比如Future.get會阻塞等等,它提供了對Future的基本實現。
可使用FutureTask包裝Callable或Runnable對象,實現異步處理線程運行結果。FutureTask實現了Runnable和Future(看源碼可以看出來),所以也可以使用api
<1>Callable使用方法
call() //類似run()方法
<2>Future使用方法
cancel(boolean mayInterruptIfRunning) //取消任務,如果已經完成,返回false isCancelled() //判斷是否取消過 isDone() //判斷是否完成,取消、完成、異常都會返回true get() //獲取執行結果,阻塞的
<3>FutureTask使用方法
cancel(boolean mayInterruptIfRunning) isCancelled() done() //重寫它來實現異步處理線程執行結果 isDone() run() get()
- 使用示例
Callable+Futrue private static class CallableThread implements Callable<String>{ @Override public String call() throws Exception { System.out.println("進入CallableThread的call()方法, 開始睡覺, 睡覺時間為" + System.currentTimeMillis()); Thread.sleep(10000); System.out.println("睡覺結束"); return "123"; } } @Test public void test2(){ ExecutorService executorService = Executors.newCachedThreadPool(); CallableThread callableThread = new CallableThread(); long l = System.currentTimeMillis(); System.out.println("任務提交前時間:" + l); Future<String> submit = executorService.submit(callableThread); try { String s = submit.get(); }catch (Exception e){ } System.out.println("獲取結果的時間:" + (System.currentTimeMillis()-l)); }
執行結果
任務提交前時間:1556438172228
進入CallableThread的call()方法, 開始睡覺, 睡覺時間為1556438172229
睡覺結束
獲取結果的時間:10006
這裏的 Future.get 是阻塞方法 , 會一直等待Callable中線程任務執行完畢,是很低下的效率,
解決方式
1.可以使用FutureTask ,重寫done方法
2.循環判斷isDone,返回true的時候然後調用get()獲取
Callable+FutureTask,異步處理線程運行結果
private static class CallableThread implements Callable<String>{
@Override
public String call() throws Exception {
System.out.println("進入CallableThread的call()方法, 開始睡覺, 睡覺時間為" + System.currentTimeMillis());
Thread.sleep(10000);
System.out.println("睡覺結束");
return "123";
}
}
private class MyFutureTask extends FutureTask<String>{
public MyFutureTask(Callable callable){
super(callable);
}
//FutureTask任務完成,會回調這個方法
@Override
protected void done() {
System.out.println("執行完調用了done()");
super.done();
try {
String s = this.get();
System.out.println("任務執行完畢:" + s);
System.out.println("當前時間:" + System.currentTimeMillis());
}catch (Exception e){
}
}
}
@Test
public void test3() {
ExecutorService executorService = Executors.newCachedThreadPool();
CallableThread callableThread = new CallableThread();
MyFutureTask myFutureTask = new MyFutureTask(callableThread);
executorService.submit(myFutureTask);
System.out.println("主線程執行結束");
try {
executorService.shutdown();
executorService.awaitTermination(12,TimeUnit.SECONDS);
} catch (Exception e) {
}finally {
executorService.shutdownNow();
}
}
執行結果
執行結果如下
主線程執行結束
進入CallableThread的call()方法, 開始睡覺, 睡覺時間為1556416923492
睡覺結束
執行完調用了done()
任務執行完畢:123
當前時間:1556416933493
java核心-多線程-線程類-Callable、Future和FutureTask