Future模式模拟

    Future模式是一种非常常见的设计模式,其核心思想就是异步调用。

1. Future模式的主要参与者

参与者 作用 备注
Main 系统启动,调用client发出请求 可以看做是一个应用
client 用于返回Data对象,立即返回FutureData,并开启一个线程装配RealData
Data 返回数据的接口
FutureData FutureData实现了Data接口,构造很快,是一个虚拟数据,需要装配RealData真实数据 也可以看做是构造一个空的Data对象,按字面意思来看就是将来的数据,还没有...,当客户端需要使用数据时需要设置成RealData对象
RealData 真实数据,起构造可能会比较慢,RealData也实现了Data接口 这个数据才是Main应用需要的

2. Future模式流程图如下:

Future模式流程图

3. Future模式的简单实现

3.1 核心接口Data
/**
 * Created with IntelliJ IDEA.
 * User: 
 * Date: 2018/12/29
 * Time: 下午6:47
 * Description: Data接口有两个重要的实现,FutureData和RealData,RealData代表的是真实数据,FutureData是真实数据的代理或者说是包装
 */
public interface Data {
    String getResult();
}
/**
 * Created with IntelliJ IDEA.
 * User: 
 * Date: 2018/12/29
 * Time: 下午6:44
 * Description: 实现Data接口,其功能是对RealData进行包装、代理,在FutureClient请求Data数据时,将立即返回一个包装好的虚拟数据(RealData的虚拟数据)
 */
public class FutureData implements Data {

    //既然FutureData是RealData对象的包装,那么久应该有一个对象的引用
    private RealData realData = null;

    //标注真实数据是否准备好
    private boolean isReady = false;

    //取数据时,如果RealData还没注入数据,则将阻塞等待
    private final ReentrantLock lock = new ReentrantLock();
    private final Condition condition = lock.newCondition();

    public void setRealData(RealData realData) {
        while (isReady) {
            //数据已经准备好,直接退出
            return;
        }
        lock.lock();
        try {
            this.realData = realData;
            this.isReady = true;
            //数据已经准备,通知阻塞在getResult()上的请求
            condition.signal();
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            lock.unlock();
        }
    }

    /**
     * 获取真实数据,如果RealData代理对象没有准备好数据,则阻塞
     *
     * @return
     */
    public String getResult() {
        lock.lock();
        try {
            while (!isReady) {
                //释放锁,同时阻塞
                condition.await();
            }
        } catch (InterruptedException e) {
            e.printStackTrace();
        } finally {
            lock.unlock();
        }
        return realData.result;
    }
}
/**
 * Created with IntelliJ IDEA.
 * User: zhouyonggui
 * Date: 2018/12/29
 * Time: 下午6:54
 * Description: RealData是最终需要使用的数据,需要返回给FutureData
 */
public class RealData implements Data {
    protected String result = null;

    /**
     * 在这个过程中,模拟数据包装
     *
     * @return
     */
    public RealData(String param) {
        StringBuffer sb = new StringBuffer();
        //假设需要很长时间的业务处理
        for (int i = 0; i < 10; i++) {
            sb.append(param);
            try {
                Thread.sleep(500);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
        result = sb.toString();
    }

    public String getResult() {
        return result;
    }
}

接下来就是client,内部主要实现了FutureData,并开启一个线程去构造RealData。在接受请求后,先返回一个FutureData对象,此时FutureData内部并没有真实数据,在需要使用数据时需要等待RealData构造完成,此时如果数据尚未准备好,则将阻塞直到有数据返回。

/**
 * Created with IntelliJ IDEA.
 * User: zyg
 * Date: 2019/1/2
 * Time: 下午9:12
 * Description:FUture客户端主要负责获取FutureData,并异步起一个线程,构造RealData
 */
public class Client {
    public Data request(final String queryStr) {
        final FutureData future = new FutureData();
        new Thread(new Runnable() {
            public void run() {
                RealData realData = new RealData(queryStr);
                future.setRealData(realData);
            }
        }).start();
        return future;
    }
}

最后是我们的Main应用,她主要是负责调用client发起请求,并消费返回的数据。

/**
 * Created with IntelliJ IDEA.
 * User: zyg
 * Date: 2019/1/2
 * Time: 下午9:21
 * Description:
 */
public class Main {
    public static void main(String[] args) {
        Client client = new Client();
        //客户端发起请求
        Data data = client.request("杨幂");
        System.out.println("客户端请求完毕!");
        //模拟其他业务
        try {
            Thread.sleep(2000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

        //使用真实数据
        System.out.println("数据=" + data.getResult());
    }
}

猜你喜欢

转载自blog.51cto.com/3265857/2346426