Java多线程 Callable和Future
1、简介
(1)先来了解一下Callable 接口
Callable是类似于Runnable的接口,实现Callable接口的类和实现Runnable的类都是可被其他线程执行的任务。Callable接口的定义如下:
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<Integer>表示一个最终返回Integer对象的异步计算。
(2)Future保存异步计算的结果。实际应用中可以启动一个计算,将Future对象交给某个线程,然后执行其他操作。Future对象的所有者在结果计算好之后就可以获得它。Future接口具有下面的方法:
public interface Future<V> {
//可以用cancel方法取消该计算。如果计算还没有开始,它被取消且不再开始。
//如果计算处于运行之中,那么如果mayInterrupt参数为true,它就被中断
boolean cancel(boolean mayInterruptIfRunning);
//判断是够被取消
boolean isCancelled();
//如果计算还在进行,isDone方法返回false;如果完成了,则返回true。
boolean isDone();
//调用被阻塞,直到计算完成
V get() throws InterruptedException, ExecutionException;
//设置等待时间,get方法的调用超时,抛出一个TimeoutException异常
V get(long timeout, TimeUnit unit) throws InterruptedException, ExecutionException, TimeoutException;
}
(3) FutureTask包装器是一种非常便利的机制,同时实现了Future和Runnable接口。FutureTask有2个构造方法
public FutureTask(Callable<V> callable) {
if (callable == null)
throw new NullPointerException();
this.callable = callable;
this.state = NEW; // ensure visibility of callable
}
public FutureTask(Runnable runnable, V result) {
this.callable = Executors.callable(runnable, result);
this.state = NEW; // ensure visibility of callable
}
创建线程的步骤一般如下:
(1)创建Callable接口的实现类,并实现call()方法,然后创建该实现类的实例;
(2)使用FutureTask类来包装Callable对象,该FutureTask对象封装了Callable对象的call()方法的返回值
(3)使用FutureTask对象作为Thread对象的target创建并启动线程(因为FutureTask实现了Runnable接口)
(4)调用FutureTask对象的get()方法来获得子线程执行结束后的返回值。
2、使用
实例:
package callableTest;
import java.util.concurrent.*;
/**
* Callable与Future的应用
* Future取得的结果类型和Callable返回的结果类型必须一致,这是通过泛型来实现。
* Callable要采用ExecutorService的submit方法提交,返回的future对象可以取消 * 任务。
* CompletionService用于提交一组Callable任务,其take方法返回已完成的一个*Callable任务对应的Future对象。
*
**/
public class CallableTest {
public static void main(String args[]) throws InterruptedException, ExecutionException {
ExecutorService service = Executors.newSingleThreadExecutor();
Future<String> future = service.submit(new Callable<String>() {
@Override
public String call() throws Exception {
return "hello world";
}
});
System.out.println("等待结果中");
System.out.println("得到的结果为:" + future.get());
ExecutorService service2 = Executors.newFixedThreadPool(10);
CompletionService<Integer> completionService = new ExecutorCompletionService<>(service2);
for(int i = 0; i < 10; ++i){
final int temp = i;
completionService.submit(new Callable<Integer>() {
@Override
public Integer call() throws Exception {
return temp;
}
});
}
for(int i = 0; i < 10; ++i){
System.out.println(completionService.take().get());
}
service.shutdown();
service2.shutdown();
}
}
结果:
等待结果中
得到的结果为:hello world
0
1
2
3
4
5
6
7
8
9