Java中除了Runnable接口,還有Callable接口。
兩者區別是,後者可以有返回值,一般用於耗時計算。
Runnable接口在線程中用得比較多,一般可以作為線程執行體,Callable一般會與FutureTask結合使用。
Callable接口的源碼如下:
/**
* A task that returns a result and may throw an exception.
* Implementors define a single method with no arguments called
* {@code call}.
* 帶有返回值的任務,可能拋出異常。
*
*
The {@code Callable} interface is similar to {@link * java.lang.Runnable}, in that both are designed for classes whose * instances are potentially executed by another thread. A * {@code Runnable}, however, does not return a result and cannot * throw a checked exception. * Callable接口類似於Runnable接口,都是設計用於被其他線程執行的類實例。 * 但是Runnable接口不返回結果,不能拋出一個受檢異常。 * *
The {@link Executors} class contains utility methods to * convert from other common forms to {@code Callable} classes. * Executors類包含將其他通用形式轉成Callable類的輔助類。 * * @see Executor * @since 1.5 * @author Doug Lea * @param
Future接口用於表示異步計算的結果,該接口包含檢查計算是否結束、等待計算結束、獲取計算結果的方法。
其中get()可以獲取計算結果,在計算完成之前,會一直阻塞當前線程。計算可以被取消。
FutureTask實現了RunnableFuture接口:
public class FutureTask implements RunnableFuture {
而RunnableFuture接口繼承自Runnable和Future:
public interface RunnableFuture extends Runnable, Future {
FutureTask表示可取消的異步計算,作為Future接口的實現。FutureTask可以包裝Runnable接口,
另外因為實現了Runnable接口,所以可以提交給Executor執行。
下面用代碼測試一下:
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.Future;
import java.util.concurrent.FutureTask;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
public class Main {
public static void main(String[] args) throws InterruptedException, ExecutionException {
Runnable runnable = new Runnable() {
@Override
public void run() {
System.out.println(runnable running);
}
};
Callable callable = new Callable() {
@Override
public Integer call() throws Exception {
System.out.println(callable running);
return 123;
}
};
Callable callable1 = new Callable() {
@Override
public Integer call() throws Exception {
System.out.println(callable1 running);
return 123;
}
};
//runnable
Thread thread1 = new Thread(runnable);
thread1.start();
//callable
FutureTask future = new FutureTask(callable);
Thread thread2 = new Thread(future);
thread2.start();
System.out.println(future is done? +future.isDone());
//future.cancel(false);
Thread.sleep(1000);
System.out.println(future result: +future.get());
ThreadPoolExecutor executor = new ThreadPoolExecutor(1, 1, 0L,
TimeUnit.MILLISECONDS, new LinkedBlockingQueue());
executor.execute(runnable);
FutureTask future1 = new FutureTask(callable1);
executor.execute(future1);
FutureTask ft = new FutureTask(runnable, aaaaa);
Thread thread3 = new Thread(ft);
thread3.start();
while(!ft.isDone()){
Thread.sleep(1000);
}
System.out.println(future runnable result: +ft.get());
Future futureTask = executor.submit(callable);
while(!futureTask.isDone()){
Thread.sleep(1000);
}
System.out.println(futureTask result: +futureTask.get());
executor.shutdown();
}
}
輸出結果:
runnable running
future is done? false
callable running
future result: 123
runnable running
callable1 running
runnable running
future runnable result: aaaaa
callable running
futureTask result: 123