概览
在多线程中有Runnable
、Callable
和Future
,那么它们之间有什么联系和区别呢?
Runnable
Runnable
接口只有一个方法:
public interface Runnable{
void run()
}
所以Runnable
是一个函数式接口(只有一个抽象方法),可以用lambda表达式建立一个实例:
Runnable r = ()->{task code};
Callable
Callable
接口是一个参数化的类型,只有一个方法Call:
public interface Callable<V>{
V call() throws Exception;
}
该方法计算结果,如果无法计算出结果,则抛出一个异常。类型参数是返回值的类型,比如Callable<Integer>
表示最终返回Integer
对象的异步计算。
Future
Future
表示异步计算的结果。它提供了检查计算是否完成的方法,以等待计算的完成,并获取计算的结果。计算完成后只能使用 get
方法来获取结果,如有必要,计算完成前可以阻塞此方法。取消则由 cancel
方法来执行。还提供了其他方法,以确定任务是正常完成还是被取消了。一旦计算完成,就不能再取消计算。如果为了可取消性而使用 Future
但又不提供可用的结果,则可以声明 Future<?>
形式类型、并返回 null
作为底层任务的结果。Future接口具有以下方法:
public interface Future<V>{
V get() throws ...;
V get(long timeout, TimeUnit unit) throws ...;
void cancel(boolean mayInterrupt);
boolean isCancelled();
boolean isDone();
}
区别
Runnable
封装一个一步运行的任务,可以看作一个没有参数和返回值的异步方法。
Callable
与Runnable
类似,但是有返回值。
联系
FutureTask
包装器可以将Callable转换成Runnable
和Future
,它同时实现二者的接口:
Callable<Integer> myComputation = ...;
FutureTask<Integer> task = new FutureTask<Integer>(myComputation);//包装
Thread t = new Thread(task);//it's a Runnable
t.start();
...
Integer result = task.get();//it's a Future