如何获取任务执行结果
Java通过ThreadPoolExecutor提供的三个submit()方法和一个FutureTask工具类来支持获得任务执行结果的需求。
// 提交Runnable任务
Future<?>
submit(Runnable task);
// 提交Callable任务
<T> Future<T>
submit(Callable<T> task);
// 提交Runnable任务及结果引用
<T> Future<T>
submit(Runnable task, T result);
Future接口有下面5个方法,其中最后一个get(timeout,unit)支持超时机制。通过Future接口的5个方法,你会发现,我们提交的任务不但能够获取任务执行结果,还可以取消任务。不过值得注意的是:这两个get方法都是阻塞式的,如果被调用的时候,任务还没有执行完,那么调用get方法的线程会阻塞,指导任务执行完才会被唤醒。
// 取消任务
boolean cancel(
boolean mayInterruptIfRunning);
// 判断任务是否已取消
boolean isCancelled();
// 判断任务是否已结束
boolean isDone();
// 获得任务执行结果
get();
// 获得任务执行结果,支持超时
get(long timeout, TimeUnit unit);
这3个submit方法之间的区别在于方法参数不同:
- 提交Runnbale任务
submit(Runnable task)
:这个方法参数Runnable的run方法是没有返回值的,所以这个方法返回的Future仅可以用来断言任务已经结束,类似于Thread.join(); - 提交Callable任务
submit(Callable<T> task)
:这个方法的参数是一个Callable接口,只有一个call方法,并且这个方法是有返回值的,可以通过get方法来获取任务执行结果。 - 提交Runnable任务及结果引用
submit(Runnable task, T result)
:假设这个方法返回Future对象时f,f.get的返回值就是传给submit方法的参数result,result相当于主线程和子线程之间的桥梁,通过它主子线程可以共享数据。
public class FutureDemo {
static class Result{
private String resultStr;
public String getResultStr() {
return resultStr;
}
public void setResultStr(String resultStr) {
this.resultStr = resultStr;
}
}
static class Task implements Runnable{
Result r;
public Task(Result r) {
this.r = r;
}
@Override
public void run() {
System.out.println(Thread.currentThread().getName() + ":" + r.getResultStr());
r.setResultStr("hello Java");
System.out.println(Thread.currentThread().getName() + ":" + r.getResultStr());
}
}
public static void main(String[] args) throws ExecutionException, InterruptedException {
ExecutorService executor = Executors.newFixedThreadPool(1);
Result result = new Result();
result.setResultStr("hello world");
Future<Result> future = executor.submit(new Task(result), result);
System.out.println(Thread.currentThread().getName() + ":" + result.getResultStr()); // hello world
System.out.println(Thread.currentThread().getName() + ":" + future.get().getResultStr()); // hello Java
}
}
FutureTask工具类
FutureTask(Callable<V> callable);
FutureTask(Runnable runnable, V result);
// 创建FutureTask
FutureTask<Integer> futureTask
= new FutureTask<>(()-> 1+2);
// 创建线程池
ExecutorService es =
Executors.newCachedThreadPool();
// 提交FutureTask
es.submit(futureTask);
// 获取计算结果
Integer result = futureTask.get();
// 创建FutureTask
FutureTask<Integer> futureTask
= new FutureTask<>(()-> 1+2);
// 创建并启动线程
Thread T1 = new Thread(futureTask);
T1.start();
// 获取计算结果
Integer result = futureTask.get();
实现最优的"烧水泡茶"程序
public static void main(String[] args) {
FutureTask<String> task2 = new FutureTask<>(()->{
System.out.println("洗茶壶");
System.out.println("洗茶杯");
System.out.println("拿茶叶");
return "茶叶AAA";
});
FutureTask task1 = new FutureTask(new FutureTask2(task2));
Thread t1 = new Thread(task1);
Thread t2 = new Thread(task2);
t1.start();
t2.start();
}
static class FutureTask2 implements Callable<String>{
FutureTask<String> f1;
public FutureTask2(FutureTask<String> f1) {
this.f1 = f1;
}
@Override
public String call() throws Exception {
System.out.println("洗水壶");
System.out.println("烧开水");
System.out.println("泡茶"+f1.get());
return "";
}
}