java併發-Callable與Future
阿新 • • 發佈:2019-01-04
基本概念:
- Callable 介面類似於 Runnable,兩者都是為那些其例項可能被另一個執行緒執行的類設計的。但是 Runnable 不會返回結果,並且無法丟擲經過檢查的異常。
- Future 表示非同步計算的結果。它提供了檢查計算是否完成的方法,以等待計算的完成,並獲取計算的結果。計算完成後只能使用 get 方法來獲取結果,如有必要,計算完成前可以阻塞此方法。取消則由 cancel 方法來執行。還提供了其他方法,以確定任務是正常完成還是被取消了。一旦計算完成,就不能再取消計算。如果為了可取消性而使用 Future 但又不提供可用的結果,則可以宣告 Future
Callable
Callable位於java.util.concurrent包下,它也是一個介面,在它裡面也只聲明瞭一個方法,只不過這個方法叫做call():
public interface Callable<V> {
/**
* Computes a result, or throws an exception if unable to do so.
*
* @return computed result
* @throws Exception if unable to compute a result
*/
V call() throws Exception;
}
可以看到,這是一個泛型介面,call()函式返回的型別就是傳遞進來的V型別。
那麼怎麼使用Callable呢?一般情況下是配合ExecutorService來使用的,在ExecutorService介面中聲明瞭若干個submit方法的過載版本:
<T> Future<T> submit(Callable<T> task)
Future<?> submit(Runnable task)
提交一個 Runnable 任務用於執行,並返回一個表示該任務的 Future。 <T> Future<T> submit(Runnable task, T result)
提交一個 Runnable 任務用於執行,並返回一個表示該任務的 Future。
Future
Future就是對於具體的Runnable或者Callable任務的執行結果進行取消、查詢是否完成、獲取結果。必要時可以通過get方法獲取執行結果,該方法會阻塞直到任務返回結果。
boolean cancel(boolean mayInterruptIfRunning)
試圖取消對此任務的執行。
V get()
如有必要,等待計算完成,然後獲取其結果。
V get(long timeout, TimeUnit unit)
如有必要,最多等待為使計算完成所給定的時間之後,獲取其結果(如果結果可用)。
boolean isCancelled()
如果在任務正常完成前將其取消,則返回 true。
boolean isDone()
如果任務已完成,則返回 true。
FutureTask
我們可以看出FutureTask實現的是:RunnableFuture
public class FutureTask<V>
extends Object
implements RunnableFuture<V>
我們再看RunnableFuture
public interface RunnableFuture<V>
extends Runnable, Future<V>
可以看出RunnableFuture繼承了Runnable介面和Future介面,而FutureTask實現了RunnableFuture介面。所以它既可以作為Runnable被執行緒執行,又可以作為Future得到Callable的返回值。
例項1:Callable+Future
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
public class test5 {
public static void main(String[] args) {
ExecutorService executor = Executors.newCachedThreadPool();
Task task = new Task();
Future<Integer> result = executor.submit(task);
executor.shutdown();
try {
Thread.sleep(1000);
} catch (InterruptedException e1) {
e1.printStackTrace();
}
System.out.println("主執行緒在執行任務");
try {
System.out.println("task執行結果"+result.get());
} catch (InterruptedException e) {
e.printStackTrace();
} catch (ExecutionException e) {
e.printStackTrace();
}
System.out.println("所有任務執行完畢");
}
}
class Task implements Callable<Integer>{
@Override
public Integer call() throws Exception {
System.out.println("子執行緒在進行計算");
Thread.sleep(3000);
int sum = 0;
for(int i=0;i<100;i++)
sum +=i;
return sum;
}
}
例項2:Callable+FutureTask
public class Test {
public static void main(String[] args) {
//第一種方式
ExecutorService executor = Executors.newCachedThreadPool();
Task task = new Task();
FutureTask<Integer> futureTask = new FutureTask<Integer>(task);
executor.submit(futureTask);
executor.shutdown();
//第二種方式,注意這種方式和第一種方式效果是類似的,只不過一個使用的是ExecutorService,一個使用的是Thread
/*Task task = new Task();
FutureTask<Integer> futureTask = new FutureTask<Integer>(task);
Thread thread = new Thread(futureTask);
thread.start();*/
try {
Thread.sleep(1000);
} catch (InterruptedException e1) {
e1.printStackTrace();
}
System.out.println("主執行緒在執行任務");
try {
System.out.println("task執行結果"+futureTask.get());
} catch (InterruptedException e) {
e.printStackTrace();
} catch (ExecutionException e) {
e.printStackTrace();
}
System.out.println("所有任務執行完畢");
}
}
class Task implements Callable<Integer>{
@Override
public Integer call() throws Exception {
System.out.println("子執行緒在進行計算");
Thread.sleep(3000);
int sum = 0;
for(int i=0;i<100;i++)
sum += i;
return sum;
}
}