1 Callable
Callable与Runnable不同(Runnable不能返回任务执行结果并且不能抛出异常),
Callable是个泛型参数化接口,并且能返回线程的执行结果,且能在无法正常计算时抛出异常
![](https://img.haomeiwen.com/i7803976/79a551bca71b803a.png)
<1> Callable并不像Runnable那样通过Thread的start方法就能启动实现类的run方法,所以它通常利用ExecutorService的submit方法去启动call方法执行任务,而ExecutorService的submit又返回一个Future类型的结果,因此Callable通常也与Future一起使用
ExecutorService pool = Executors.newCachedThreadPool();
Future<String> future = pool.submit(new Callable{
public void call(){
//TODO
}
});
或者利用FutureTask封装Callable,再由Thread去启动(少用)
FutureTask<String> task = new FutureTask(new Callable{
public void call(){
//TODO
}
});
Thead thread = new Thread(task);
thread.start();
<2> 通过Executors.callbale(Runnable task,T result)可以执行Runnable并返回"结果",但是这个结果并不是Runnable的执行结果(Runnable的run方法是void类型),而是执行者预定义的结果,这点可以从其实现原理RunnableAdpter源码看出
public static <T> Callable<T> callable(Runnable task, T result) {
if (task == null)
throw new NullPointerException();
return new RunnableAdapter<T>(task, result);//通过RunnableAdapter实现
}
static final class RunnableAdapter<T> implements Callable<T> {
final Runnable task;
final T result;
RunnableAdapter(Runnable task, T result) {
this.task = task;
this.result = result;
}
public T call() {
task.run();
return result; //将传入的结果的直接返回
}
}
实例:
final Integer[] result={null};
Runnable runnable=new Runnable() {
@Override
public void run() {
result[0]=1111;
}
};
//定义一个线程池
ExecutorService executorService= Executors.newCachedThreadPool();
//1.Executors.callable(runnable) 转换成Callable<Object>,Future返回null
Callable<Object> callable=Executors.callable(runnable);
Future future=executorService.submit(callable);
//输出运行结果,肯定是null
System.out.println("Executors.callable(runnable) 的future = " + future.get());
//2.Executors.callable(runnable,result) 转换成Callable<V>,future有值
Callable<Integer> callable1=Executors.callable(runnable,result[0]);
Future future1=executorService.submit(callable1);
System.out.println("Executors.callable(runnable, result) 的future = " + future1.get());
执行结果:
![](https://img.haomeiwen.com/i7803976/d02bb2e81732f5fd.png)
Runnable与Callable不同点:
- Runnable不返回任务执行结果,Callable可返回任务执行结果
- Callable在任务无法计算结果时抛出异常,而Runnable不能
- Runnable任务可直接由Thread的start方法或ExecutorService的submit方法去执行
2 Future
Future就是对于具体的Runable或者Callable任务的执行结果进行取消、查询是否完成、获取结果。必要时可以通过get方法获取执行结果,该方法会阻塞直到任务返回结果。
![](https://img.haomeiwen.com/i7803976/29644b0e76209769.png)
-
cancel(boolean mayInterruptIfRunning):试图取消执行的任务,如果取消任务成功则返回true,如果取消任务失败则返回false。
参数mayInterruptIfRunning表示是否允许取消正在执行却没有执行完毕的任务,如果设置true,则表示可以取消正在执行过程中的任务。
如果任务已经完成,则无论mayInterruptIfRunning为true还是false,此方法肯定返回false,即如果取消已经完成的任务会返回false;
如果任务正在执行,若mayInterruptIfRunning设置为true,则返回true,若mayInterruptIfRunning设置为false,则返回false;
如果任务还没有执行,则无论mayInterruptIfRunning为true还是false,肯定返回true。 -
isCancelled():判断任务是否在正常执行完前被取消的,如果是则返回true
-
isDone():判断任务是否已完成
-
get():等待计算结果的返回,这个方法会产生阻塞,会一直等到任务执行完毕才返回,如果计算被取消了则抛出
-
get(long timeout,TimeUtil unit):设定计算结果的返回时间,如果在规定时间内没有返回计算结果则抛出TimeOutException
使用Future的好处:
- 获取任务的结果,判断任务是否完成,中断任务
- Future的get方法很好的替代的了Thread.join或Thread,join(long millis)
- Future的get方法可以判断程序代码(任务)的执行是否超时,如:
try{
future.get(60,TimeUtil.SECOND);
}catch(TimeoutException timeout){
log4j.log("任务越野,将被取消!!");
future.cancel();
}
总结:自Java1.5之后,通过Callable和Future的配合使用,可以在任务执行完毕之后得到任务的执行结果
3 FutureTask
FutureTask实现RunableFuture接口,这个接口的定义如下:
public interface RunnableFuture<V> extends Runnable, Future<V> {
void run();
}
可以看到这个接口实现了Runnable和Future接口,接口中的具体实现由FutureTask来实现。这个类的两个构造方法如下:
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
}
如上提供了两个构造函数,一个以Callable为参数,另外一个以Runnable为参数。这些类之间的关联对于任务建模的办法非常灵活,允许你基于FutureTask的Runnable特性(因为它实现了Runnable接口),把任务写成Callable,然后封装进一个由执行者调度并在必要时可以取消的FutureTask。
实例:
public class FutureTaskExample {
public static void main(String[] args) {
MyCallable callable1 = new MyCallable(1000);
MyCallable callable2 = new MyCallable(2000);
FutureTask<String> futureTask1 = new FutureTask<String>(callable1);
FutureTask<String> futureTask2 = new FutureTask<String>(callable2);
ExecutorService executor = Executors.newFixedThreadPool(2);
executor.execute(futureTask1);
executor.execute(futureTask2);
while (true) {
try {
if (futureTask1.isDone() && futureTask2.isDone()) { //两个任务全都完成
System.out.println("Done");
executor.shutdown(); //关闭线程池和服务
return;
}
if (!futureTask1.isDone()) { // 任务1没有完成,会等待,直到任务完成
System.out.println("FutureTask1 output=" + futureTask1.get());
}
System.out.println("Waiting for FutureTask2 to complete");
String s = futureTask2.get(200L, TimeUnit.MILLISECONDS);
if (s != null) {
System.out.println("FutureTask2 output=" + s);
}
} catch (InterruptedException | ExecutionException e) {
e.printStackTrace();
} catch (TimeoutException e) {
//do nothing
}
}
}
private static class MyCallable implements Callable<String> {
private long waitTime;
public MyCallable(int timeInMillis) {
this.waitTime = timeInMillis;
}
@Override
public String call() throws Exception {
Thread.sleep(waitTime);
return Thread.currentThread().getName();
}
}
}
结果显示:
![](https://img.haomeiwen.com/i7803976/a26ad77ee0e9b2db.png)
网友评论