一、简介
Callable接口,其实跟Runnable接口的使用差不多,只不过Callable接口可以有返回值,返回结果并可能引发异常的任务。但是,Runnable不返回结果,也不能抛出checked异常。
二、源码
@FunctionalInterface
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;
}
Callable接口是一个函数式接口,实现Callable接口必须实现call()方法,该方法有一个返回值。
三、示例
多线程的创建方式除了使用Runnable接口,继承Thread类之外,还可以实现Callable接口。但是需要借助一下FutureTask类:
可见,FutureTask实现了RunnableFuture接口,而RunnableFuture接口又是从Runnable接口继承过来的。
主要构造方法:可以传入Callable实现类接口。
public FutureTask(Callable<V> callable) {
if (callable == null)
throw new NullPointerException();
this.callable = callable;
this.state = NEW; // ensure visibility of callable
}
下面,我们使用Callable接口创建线程:
public class T02_Callable {
public static void main(String[] args) {
FutureTask<Integer> futureTask = new FutureTask<>(new TestCallable());
new Thread(futureTask).start();
Integer result = null;
try {
//get方法会阻塞直到结果准备好
result = futureTask.get();
} catch (InterruptedException | ExecutionException e) {
e.printStackTrace();
}
System.out.println("result = " + result);
}
}
/**
* 实现Callable,并指定方法返回值类型为Integer泛型
* 1. 方法有返回值
* 2. 可以抛出异常throws Exception
*/
class TestCallable implements Callable<Integer> {
@Override
public Integer call() throws Exception {
int sum = 0;
for (int i = 0; i <= 100; i++) {
sum += i;
}
return sum;
}
}
运行结果:
result = 5050
四、总结
Callable 和 Runnable接口的区别:
- Callable必须实现的方法是call(),Runnable必须实现的方法是run();
- Callable接口在线程执行完后可以有返回值,Runnable接口并没有;
- Callable接口可以抛出异常,Runnable接口不可以抛出异常;