所谓的未来设计模式就是不需要线程阻塞,提前把结果反馈给你。在我们日常开发中经常有这样的场景:我们需要等待一个线程返回结果后,根据这个结果才能执行下面的逻辑。
下面的代码就演示了这个场景:
public class SyncInvoker {
public static void main(String[] args) {
String result = getResult();
System.out.println(result);
System.out.println("---------------");
System.out.println("-- do other thing --");
}
public static String getResult() {
try {
Thread.sleep(100000L);
} catch (InterruptedException e) {
e.printStackTrace();
}
return "ok";
}
}
要干别的事情就需要getResult返回结果,就会阻塞很久。所以随之而生的未来设计模式。
为方便理解,我们先从生活中的例子出发:
假如我们上午9点去蛋糕店定做一个蛋糕,交完钱蛋糕店提供一个收据,凭借收据进行蛋糕的领取,店员让你下午3点去拿蛋糕或者你留下一个地址,他给送货上门。
串行:一直等到下午3点拿了蛋糕,再去做其他的事情。
并行wait:三点做好,一点就去在那等着,等到蛋糕做好后,再去做其他的事情。
回调:你在定蛋糕的时候,留下了一个电话或者地址,等到做好后,用收据作为标示,要么电话通知你取,要么按照地址送货上门。
其中:做蛋糕—>FutureTask , CallBack—>具体地址 ,Future—>收据
具体代码演示:
Future 用来代表未来的一个结果
FutureTask 执行的任务逻辑
FutureService 桥接 Future和FutureTask
//去获取结果
public interface Future<T> {
T get() throws InterruptedException;
}
//获取结果的具体实现
public class AsynFuture<T> implements Future<T> {
private volatile boolean done = false;
private T result;
public void done(T result) {
synchronized (this) {
this.result = result;
this.done = true;
this.notifyAll();
}
}
//done he get 不一定是同一个线程
@Override
public T get() throws InterruptedException {
synchronized (this) {
while (!done) {
this.wait();
}
}
return result;
}
}
//具体的任务、需要干的活
public interface FutureTask<T> {
//真正干活的
T call();
}
//用来连接Future和FutureTask
public class FutureService {
//第一种情况:自己拿
public <T> Future<T> submit(final FutureTask<T> task) {
AsynFuture<T> asynFuture = new AsynFuture<>();
new Thread(() -> {
T result = task.call();
asynFuture.done(result);
}).start();
return asynFuture;
}
//第二种:做好了直接回调给我
public <T> Future<T> submit(final FutureTask<T> task, final Consumer<T> consumer) {
AsycFuture asycFuture = new AsycFuture();
new Thread(() -> {
T result = task.call();
asycFuture.done(result);
consumer.accept(result);
}).start();
return asycFuture;
}
}
//测试一下、此时线程没有阻塞、会先去执行 do other thing
public class SyncInvoker {
public static void main(String[] args) throws InterruptedException {
//测试第一种:自己拿
FutureService futureService = new FutureService();
Future submit = futureService.submit(() -> {
try {
Thread.sleep(5000);
} catch (InterruptedException e) {
e.printStackTrace();
}
return "--finish--";
});
System.out.println("-------");
System.out.println(" do other thing ");
Thread.sleep(100);
System.out.println("---------");
System.out.println(submit.get());
//测试第二种:直接送货上门(输出)
FutureService futureService = new FutureService();
futureService.submit(() -> {
try {
Thread.sleep(5000);
} catch (InterruptedException e) {
e.printStackTrace();
}
return "--finish--";
}, System.out::println);
System.out.println("-------");
System.out.println(" do other thing ");
Thread.sleep(100);
System.out.println("---------");
}
}