1、什么是future
Future是为了解决同步调用必须等待调用执行结束后返回而设计的,future中文含义是“未来”,即调用方可以在未来某个时刻通过future来获取调用结果。
通俗来讲,future相当于一个票据,你拿着这个票据就可以在未来某个时点来兑现票据承诺的内容。
以订蛋糕为例:
第一种方式:你直接到店里说我要买一个蛋糕,然后一直坐在店里等直到蛋糕制作完成,不给你做好蛋糕你就一直等,然后你也干不了别的事情(比如先去买个鲜花)。
第二种方式:你到店里预定了一个蛋糕,工作人员给了你一张凭据,让你先忙别的(如买鲜花,回家布置一下),说做好了会通知你凭票取走蛋糕。
第三种方式:和第二种类似,只是你拿着票据后,买好鲜花后也没别的事情,然后就一直在店里催好了没有(工作人员还可以忙别的事情),直到蛋糕店做好。
Future提供了一种异步调用的方式,等待被调用方返回处理结果(调用方可能同时处理多个任务),调用时立即返回,返回的是一个票据或者凭证,调用方在未来某个时点可以获取调用结果。
2、java.util.concurrent.Future
public static void main(String[] args) throws Exception {
Callable<String> task = () -> {
TimeUnit.SECONDS.sleep(3);
return "hello world";
};
ExecutorService executorService = Executors.newFixedThreadPool(1);
Future<String> future = executorService.submit(task);
System.out.println("do something");
System.out.println(future.get());
}
上面的代码创建了一个获取字符串"hello world"的任务,需要花费3s的时间。
使用线程池提交该任务后立即返回一个future,程序继续执行System.out.println(“do something”);
打印出了"do something",等待3s后打印出了"hello world"。
那么,Future是怎么实现的呢?下面我们自己实现一个,原理都是一样的
3、自己动手实现一个future设计模式
原理:
1、提交任务是立即返回一个票据,这里是FutureResult
2、有一个线程池不断的从队列里取出任务进行处理,当任务处理结束时通知
futureResult.setFuture()
3、当从FutureResult获取结果,即调用getResult
时,判断是否处理完成,未完成则等待,直到flag=true
public T getResult() {
while (!flag) {
try {
TimeUnit.MICROSECONDS.sleep(1);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
return future.getResult();
}
完整代码如下
public class FutureDIYExample {
public static void main(String[] args) throws Exception {
Callable<String> task = () -> {
TimeUnit.SECONDS.sleep(3);
return "hello world";
};
ThreadPoolService threadPoolService = new ThreadPoolService();
Future<String> f = threadPoolService.submit(task);
System.out.println("do something");
System.out.println(f.getResult());
}
private interface Future<T> {
T getResult();
}
/**
* 执行结果
* @param <T>
*/
private static class FutureResult<T> implements Future<T> {
private final Callable<T> task;
private Future<T> future;
private volatile boolean flag = false;
public FutureResult(Callable<T> task) {
this.task = task;
}
@Override
public T getResult() {
while (!flag) {
try {
TimeUnit.MICROSECONDS.sleep(1);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
return future.getResult();
}
public void setFuture(Future<T> future) {
this.future = future;
this.flag = true;
}
public Callable<T> getTask() {
return task;
}
}
/**
* 真正的执行结果
* @param <T>
*/
private static class FutureRealResult<T> implements Future<T> {
private final T result;
public FutureRealResult(T result) {
this.result = result;
}
@Override
public T getResult() {
return result;
}
}
private static class ThreadPoolService {
private final LinkedList<FutureResult> queue = new LinkedList<>();
private ExecutorService threadPool = Executors.newFixedThreadPool(1);
public ThreadPoolService() {
threadPool.execute(this::handleTask);
}
/**
* 提交任务到队列
* @param task
* @param <T>
* @return
*/
public <T> Future<T> submit(Callable<T> task) {
FutureResult<T> future = new FutureResult<>(task);
synchronized (queue) {
this.queue.add(future);
queue.notify();
}
return future;
}
/**
* 处理队列里的任务
*/
private void handleTask() {
while (true) {
FutureResult futureResult;
synchronized (queue) {
if (queue.isEmpty()) {
try {
queue.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
futureResult = queue.removeFirst();
}
Callable task = futureResult.getTask();
try {
futureResult.setFuture(new FutureRealResult(task.call()));
TimeUnit.SECONDS.sleep(1);
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
}