一、Callable的简介
Callable是Java1.5中引入的一个接口,直接看官方文档:
public interface Callable<V>
A task that returns a result and may throw an exception. Implementors define a single method with no arguments called call.The Callable interface is similar to
Runnable
, in that both are designed for classes whose instances are potentially executed by another thread. A Runnable, however, does not return a result and cannot throw a checked exception.The
Executors
class contains utility methods to convert from other common forms to Callable classes.
- Since:
- 1.5
英文比较差,翻译有些“羞涩”,但还是总结为如下三点:
1、有一个无参数的call()方法,有返回值,也会抛出异常
2、Callable是类似于Runnable的接口,实现Callable接口的类和实现Runnable的类都是可被其它线程执行的任务。
3、Callable会返回执行结果和抛出一个checked exception,但是Runnable不会
从上面信息可以看出,Callable是带有返回值的”Runnable“
二、Callable和Runnable的比较
1、相同点
Callable和Runnable都是接口。
2、不同点
1、Callable返回的是V(泛型),也就支持多个类型;Runnable不支持
2、Callable可以抛出checked exception;Runnable不可以
3、Callable执行的方法是call(),并有结果返回;Runnable执行的方法是run(),且不返回结果
4、Callable和Runnable都可以应用于executors,而Thread类只支持Runnable
三、Callable的使用
//测试代码1
Callable<Integer> callable = new Callable<Integer>() {
@Override
public Integer call() throws Exception {
Thread.sleep(3000); //延迟3秒
return (int) (Math.random() * 100);
}
};
//FutureTask实现于RunnableFuture,而RunableFuture继承于Runnable和Future
FutureTask<Integer> futureTask = new FutureTask<>(callable);
//Thread中只支持Runnable
new Thread(futureTask).start();
try {
//get()会阻塞,直到获取到结果
Log.d(TAG, "----------random:"+ futureTask.get());
} catch (InterruptedException e) {
e.printStackTrace();
} catch (ExecutionException e) {
e.printStackTrace();
}
//测试代码2
Callable<Integer> callable = new Callable<Integer>() {
@Override
public Integer call() throws Exception {
Thread.sleep(3000);
return (int) (Math.random() * 100);
}
};
//创建一个单线程
ExecutorService executorService = Executors.newSingleThreadExecutor();
Future<Integer> future = executorService.submit(callable);
try {
Log.d(TAG, "--------------------random:" + future.get());
} catch (InterruptedException e) {
e.printStackTrace();
} catch (ExecutionException e) {
e.printStackTrace();
}
//shut down
executorService.shutdown();
通过实验可以看出:
1. Callable的call()方法是运行在子线程中
2. Callable不能直接由Thread启动,需要通过FutureTask进一步转换
3. futureTask.get()方法如果没获取到结果,会一直阻塞
4. Executors中通过submit()方法执行Callable;通过execute()执行Runable