Future模式的简单实现

Future模式的简单实现

From 《Java 高并发程序设计》

  Future模式,核心思想是异步调用,就是当调用一个方法时,这个函数可能执行得很慢,就需要等待,但是有时候并不着急要这个结果,所以选择不去傻傻等待,而是做其他的事情。就好比”双十一”购物,你买到了想要的东西,那么你不可能等待它到货,然后才做另一件事情,你可能想继续购物其他的商品。而对于已经购买得商品,会生成一个订单,你只需要等待这个订单的快递通知(notify)就行了。

  Future英文翻译为未来,可以认为无法立即给你想要的数据,但是给你一个标识,在未来你可以通过这个标识取获取想要的数据。这让我想到了Node.js的异步IO,事件驱动。

  做一个简单的实现,类图是根据写的代码通过IDEA自动生成出来的,仅供参考。如下:定义一个接口Data,然后让FutureData和RealData实现它,并且,RealData是真正需要的数据,构建事件比较慢,而FutureData可以直接返回给调用者,Client执行方法,开启一个线程,去构建一个RealData,并返回一个FutureData,FutureData返回后,在RealData被构建完成后被填满,由于此时FutureData已经返回,程序可以继续执行向下耗时操作。

  在Main方法中调用FutureData的getResult()方法,会发生wait()阻塞,直到FutureDat的setRealData()方法执行完毕,notifyAll所有的阻塞线程。注意wait和notify需要包含在synchronized语句中。


Data


    package future;

    /**
     * 文件描述:
     * 作者: bamboo
     * 时间: 2016/11/28
     */
    public interface Data {
        String getResult();
    }

RealData


构造很慢,使用sleep模拟操作。

     package future;

    /**
     * 文件描述:
     * 作者: bamboo
     * 时间: 2016/11/28
     */
    public class RealData implements Data {
        protected final String result;

        public RealData(String data) {
            //设定构造函数构造得非常慢
            StringBuffer sb = new StringBuffer();
            for (int i = 0; i < 10; i++) {
                sb.append(data);
            }
            try {
                System.out.println("构建需要10s,所以先做其他的事情");
                Thread.sleep(10000);//10s 真的很慢了
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            this.result = sb.toString();
        }

        @Override
        public String getResult() {
            return result;
        }
    }

FutureData,是真实数据的代理。


让所有想要getResult的方法等待,并在构建数据完成的时候通知所有的线程,用到锁。

package future;

    /**
     * 文件描述:
     * 作者: bamboo
     * 时间: 2016/11/28
     */
    public class FutureData implements Data {
        protected RealData realData = null;
        protected Boolean isReady = false;

        public synchronized void setRealData(RealData realData) {
            if (isReady) return;
            this.realData = realData;
            isReady = true;
            notifyAll();
        }

        @Override
        public synchronized String getResult() {
            while (!isReady) {
                try {
                    wait();
                } catch (InterruptedException e) {
                }
            }
            return realData.result;
        }
    }

Client

在请求数据的时候开启一个线程去获取数据,立即返回一个futureData,此时的futureData中并没有包含想要的RealData数据。

package future;

    /**
     * 文件描述:
     * 作者: bamboo
     * 时间: 2016/11/28
     */
    public class Client {
        public Data request(final String queryStr) {
            final FutureData futureData = new FutureData();
            new Thread() {
                @Override
                public void run() {
                    RealData realData = new RealData(queryStr);
                    futureData.setRealData(realData);
                }
            }.start();
            return futureData;
        }
    }

Main

package future;

    /**
     * 文件描述:
     * 作者: bamboo
     * 时间: 2016/11/28
     */
    public class Main {
        public static void main(String[] args) {
            Client client = new Client();
            Data data = client.request("name");
            System.out.println("请求完毕");
            try {
                //用数据处理代替一个很慢的过程
                Thread.sleep(2000);
                System.out.println("快速响应的数据");
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println("数据: " + data.getResult()); //在此处阻塞。
        }
    }

测试输出

future.Main
    请求完毕
    构建需要10s,所以先做其他的事情
    快速响应的数据
    数据: namenamenamenamenamenamenamenamenamename

    Process finished with exit code 0
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值