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

原文地址:https://www.cnblogs.com/liuligang/p/10571390.html