Callable
Callable与Runnable类似,但是执行任务后能返回结果;Future接口表示异步任务,它能拿到Callable的返回值,即获取结果。
Callable接口如下:
public interface Callable<V> {
V call() throws Exception;
}
这是一个泛型接口,返回的类型就是传递进来的类型,或者抛出异常。
使用: 一般作为参数,详见后面的例子
Future
Future能具体的Runnable或者Callable任务的执行进行取消、查询是否完成、获取结果。
接口如下:
public interface Future<V> {
// 取消对此任务的执行
boolean cancel(boolean mayInterruptIfRunning);
// 如果在任务正常完成前将其取消,则返回 true
boolean isCancelled();
// 如果任务已完成返回 true
boolean isDone();
// 获取执行结果,该方法会阻塞一直等到任务执行完成
V get() throws InterruptedException, ExecutionException;
// 最多等待为使计算完成所给定的时间之后,获取其结果,如果超时,结果返回null
V get(long timeout, TimeUnit unit) throws InterruptedException, ExecutionException, TimeoutException;
}
Future的实现类:FutureTask
public class FutureTask<V> implements RunnableFuture<V> {
……
public interface RunnableFuture<V> extends Runnable, Future<V> {
void run();
}
可以看到,FutureTask实现了Runnable和Future,既可以作为Runnable被线程执行,又可以作为Future得到Callable的返回值。
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
}
示例如下
使用场景:当前线程(线程A)需要依赖于另一个线程(线程B)的处理结果,而线程B处理结果需要一定的时间,Future模式就可以让线程A的数据请求交给B,需要数据时再去get。而在B处理时A还能处理其他业务。
package com.learn;
import java.util.concurrent.Callable;
public class FooCallable implements Callable<String> {
private String name;
public FooCallable(String name) {
this.name = name;
}
@Override
public String call() throws Exception {
System.out.println("Task任务执行");
Thread.sleep();
return name;
}
}
package com.learn;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.FutureTask;
public class FutureTaskTest {
public static void main(String[] args) {
FooCallable a = new FooCallable("A");
FutureTask<String> futureTask1 = new FutureTask<>(a);
ExecutorService executorService = Executors.newCachedThreadPool();
executorService.submit(futureTask1);
System.out.println("主线程执行任务");
try {
if (!futureTask1.isDone()) { // 任务没有完成,会等待,直到任务完成
System.out.println("FutureTask执行结果" + futureTask1.get());
}
} catch (Exception e) {
e.printStackTrace();
}
executorService.shutdown();
System.out.println("All执行完毕");
}
}
执行结果:
Task任务执行
主线程执行任务
FutureTask执行结果A
All执行完毕
示例2
采用submit(Callable)
package com.learn;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
public class FutureTaskTest {
public static void main(String[] args) {
FooCallable a = new FooCallable("A");
ExecutorService executorService = Executors.newCachedThreadPool();
Future<String> ret = executorService.submit(a);
System.out.println("主线程执行任务");
try {
System.out.println("Task执行结果" + ret.get());
} catch (Exception e) {
e.printStackTrace();
}
executorService.shutdown();
System.out.println("All执行完毕");
}
}