Future设计模式
Future设计模式
示列引入
如上图,传统的订单下单流程,首先减商品库存,然后生成订单,然后生成订单详情,再通知短信等等,全部逻辑程序都是串行执行的.假如我们的系统特别'困难',减商品库存要1秒,生成订单要1秒,生成详情也要1秒,发送短信有可能要5秒,这里还不算查询商品的库存够不够下单等等,那么一系列的操作就要花很多时间。
那么引入Future模式有什么好处呢?
future对象直接告诉你下单成功,返回给一个假数据,同时自己偷偷的建一个或者几个线程来处理业务逻辑,等业务逻辑处理完了,再返回一个正确的结果。
示列代码
/**
返回数据接口
*/
public interface Data {
String getRequest();
}
/**
RealData:真实数据,构造很慢的
*/
public class RealData implements Data {
protected String result;
public RealData(String para) {
StringBuffer sb = new StringBuffer();
for (int i = 0; i < 10; i++) {
sb.append(para);
try {
Thread.sleep(100);
} catch (Exception e) {
// TODO: handle exception
}
result = sb.toString();
}
}
@Override
public String getRequest() {
return result;
}
}
/**
FutureData,当有线程想要获取RealData的时候,程序会被阻塞。等到RealData被注入才会使用getReal()方法
FutureData:构造很快,但是是一个虚拟数据,需要装配
*/
public class FutureData implements Data {
protected RealData realData = null;
protected boolean isReady = false;
@Override
public synchronized String getRequest() {
while (!isReady) {
try {
this.wait();
} catch (InterruptedException e) {
break;
}
}
return realData.result;
}
public synchronized void setRealData(RealData realData) {
if (isReady)
return;
this.realData = realData;
isReady = true;
notifyAll();
}
}
/**
Client:返回Data对象,立即返回FutureData,并开启线程装配RealData
*/
public class Client {
public Data request(String queryStr) {
final FutureData futureData = new FutureData();
new Thread(() -> {
RealData realData = new RealData(queryStr);
futureData.setRealData(realData);
}).start();
return futureData;
}
}
public class Main {
public static void main(String[] args) throws InterruptedException {
Client client = new Client();
//立即返回
Data data = client.request("xxx");
System.out.println("请求发送完毕。。。");
//模拟客户端其他操作
Thread.sleep(2000);
//调用真实数据
System.out.println(data.getRequest());
}
}
总结
Future模式对于多线程而言,如果线程A要等待线程B的结果,那么线程A没必要一直等待B,直到B有结果,可以先拿到一个未来的Future,等B有结果时再获取真实的结果。
Future模式JDK支持
public interface Future<T> {
T get() throws InterruptedException;
}
//返回的Future票据
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();
}
}
@Override
public T get() throws InterruptedException {
synchronized (this) {
//这里不应该一直等待
while (!done) {
this.wait();
}
}
return result;
}
}
/**
*JDK中的FutureTask,public class FutureTask<V> implements RunnableFuture<V>
其直接实现了Runnable接口,作为单独的线程启动,其中run()方法中,通过调用构造传递
的Callable接口调用call()方法
*/
public interface FutureTask<T> {
T call();
}
public class FutureService {
public <T> Future<T> submit(FutureTask task){
AsynFuture<T> asynFuture = new AsynFuture<>();
//开启线程直接处理,只是这里因为我们的FutureTask并没有继承Runnable接口,所以这里我们手动开启一个线程
new Thread(() -> {
T result = (T) task.call();
asynFuture.done(result);
}).start();
return asynFuture;
}
//这是直接对处理结果进行处理,而不用返回Future
public <T> void submit(FutureTask task, Consumer<T> consumer){
// AsynFuture<T> asynFuture = new AsynFuture<>();
new Thread(() -> {
T result = (T) task.call();
// asynFuture.done(result);
consumer.accept(result);
}).start();
// return asynFuture;
}
}
public class SyncInvoker {
public static void main(String[] args) throws InterruptedException {
FutureService service = new FutureService();
Future<String> future = service.submit(() -> {
try {
Thread.sleep(10000);
} catch (InterruptedException e) {
e.printStackTrace();
}
return "FINISH";
});
service.submit(() -> {
try {
Thread.sleep(10000);
} catch (InterruptedException e) {
e.printStackTrace();
}
return "FINISH";
},System.out::println);
System.out.println("=========================");
System.out.println(" do other thing ");
TimeUnit.SECONDS.sleep(1);
System.out.println("==========================");
System.out.println(future.get());
}
}
参考博客
高并发设计思想之Future模式:https://baijiahao.baidu.com/s?id=1614584183229617943&wfr=spider&for=pc