Future,你只需看这一篇就够了
程序员文章站
2022-06-05 19:50:21
...
如题:最近在读组内kafka项目的代码,看到有关future的用法, 总结一下。
Future主要是用于获取线程执行任务结果。
Java通过ThreadPoolExecutor中的3个Submit方法,和一个FutureTask工具类来获取线程任务执行结果。这三个submit的方法签名如下:
// 提交 Runnable 任务
Future<?> submit(Runnable task);
// 提交 Callable 任务
<T> Future<T> submit(Callable<T> task);
// 提交 Runnable 任务及结果引用
<T> Future<T> submit(Runnable task, T result);
下面简单介绍一下这三个方法:
1 方法1的参数是Runnable,这个对象中的run方法是没有返回值的,所以我们通过它只能判断任务是否执行完毕
2 方法2的参数是Callable,这个对象中的call方法是有返回值的,所以可以通过future中的get方法来获取任务执行的返回值
3 方法3比较特殊,其中的result是主线程和工作线程的桥梁,我们可以将task中的的执行结果存储在result中,下面的示例代码简述了它的用法:
ExecutorService executor = Executors.newFixedThreadPool(1);
Result r = new Result();
r.setAAA(a);
// 提交任务
Future<Result> future = executor.submit(new Task(r), r);
Result fr = future.get();
// 下面等式成立
fr === r;
fr.getAAA() === a;
fr.getXXX() === x
class Task implements Runnable{
Result r;
// 通过构造函数传入 result
Task(Result r){
this.r = r;
}
void run() {
// 可以操作 result
a = r.getAAA();
r.setXXX(x);
}
}
Future的核心方法有5个,方法签名如下:
// 取消任务
boolean cancel(boolean mayInterruptIfRunning);
// 判断任务是否已取消
boolean isCancelled();
// 判断任务是否已结束
boolean isDone();
// 获得任务执行结果
get();
// 获得任务执行结果,支持超时
get(long timeout, TimeUnit unit);
值得注意的是,get方法是阻塞方法, 建议使用带有超时时间的get方法。
学会了Future和Runnable的用法,那么再去理解FutureTask就会容易很多,因为Future其实就是实现了Runnable和Future的工具类,所以它既可以作为一个Task,被线程执行,又因为它实现了Future接口,所以它也可以用来获取任务执行结果。
public class FutureTask<V> implements RunnableFuture<V>
public interface RunnableFuture<V> extends Runnable, Future<V> {
/**
* Sets this Future to the result of its computation
* unless it has been cancelled.
*/
void run();
}
它的构造方法如下:
FutureTask(Callable<V> callable);
FutureTask(Runnable runnable, V result);
使用FutureTask的示例代码如下:
// 创建 FutureTask
FutureTask<Integer> futureTask = new FutureTask<>(()-> 1+2);
// 创建线程池
ExecutorService es = Executors.newCachedThreadPool();
// 提交 FutureTask
es.submit(futureTask);
// 获取计算结果
Integer result = futureTask.get();
直接使用FutureTask执行的案例:
// 创建 FutureTask
FutureTask<Integer> futureTask = new FutureTask<>(()-> 1+2);
// 创建并启动线程
new Thread(futureTask).start();
// 获取计算结果
Integer result = futureTask.get();