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();
}
}
}
}
}