Future三重奏第一章:Future设计模式及代码示例

Future系列文章

Future三重奏第一章:Future设计模式及代码示例
Future三重奏第二章:FutureTask源码解析

Future模式的作用

去除等待主函数执行某项耗时操作的等待时间,在执行主函数耗时业务操作的时候,及时返回一个数据,继续主函数剩下的业务,当需要获取之前耗时操作的结果的时候在进行获取

其本质则是在维持主业务顺利进行的同时,异步的执行主业务中的耗时分业务,使得原本需要进行等待的时间可以处理其他的业务

###实际业务场景:
在开具电子发票的业务中,当我们申请开电子发票的时候,电子发票并不会立即开票成功,而是需要调取第三方接口,第三方接口在返回告诉我们是否开具成功,这时候需要等待一段时间才能得到开票结果,在等待第三方返回结果的同时,这个时候我们还有其他别的业务要进行处理返回,不可能一直等待第三方返回的数据,这时候我们就可以采用future模式,将该方法改为异步处理,在等待数据返回的时候进行其他业务的处理

future模式核心类作用

此处通过几个简单的类来展示future模式的思路和运行方式
Main类:系统启动类,调用Client类发出业务请求
Client类:该类在接收到构造并返回FutureData类,返回的FutureData类是一个虚假的对象,或者说并不是一个拥有实际数据的对象,Client的核心在于构建一个新的线程去执行RealData类,该类是处理耗时的业务类
Data:获取实际数据的接口,futureData类和realData类需要实现该接口
FutureData类:及时返回调用类,内部封装了实际数据,可通过该类获取实际的业务数据
RealData:实际的业务处理类,耗时较长

future模式示例代码

Main类

发起请求,构建执行了Client类,返回了Data对象,并在最后调用了data对象实际获取到的数据

public class Main {

    public static void main(String args[]){
        Client client=new Client();

        //调用client发送请求
        Data data=client.request("Hello Future!");

        System.out.println("请求完毕!");

        try {
            //模拟处理其他业务
            Thread.sleep(2000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

        //调用实际返回的数据
        System.out.println("真实数据:" + data.getResult());

    }
}

Data接口

Main类中实际返回Data对象,该接口提供获取数据的方法

public interface Data {

    String getResult();
}

Client类

在主类中构建的Client类,并返回futureData对象,另一方面通过该类生成线程发出异步请求,新线程中执行业务类,并返回计算结果,将计算结果封装进futureData对象中

public class Client {

    public Data request(String param){

        //立即返回futureData
        FutureData futureData=new FutureData();

        //需要启动一个新线程
        //开启ClientThread线程装配realData
        new Thread(() -> {
            //装配realData
            //RealData为业务类,传递相关参数过去
            RealData realData=new RealData(param);

            //获取到数据后将数据封装进实体类中
            futureData.setRealData(realData);

        }).start();
        return futureData;
    }
}

RealData类

实际业务类,该类主要是执行业务方法并得到计算结果,并提供获取数据的方法

public class RealData implements Data{

    private String result;//封装实际数据


    /**
     * 获取计算结果方法
     * @return
     */
    @Override
    public String getResult() {
        return result;
    }

    public RealData(String param){
        StringBuffer sb=new StringBuffer();

        sb.append(param);

        //模拟业务执行
        //此处通过线程睡眠的方式
        try {
            Thread.sleep(1000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

        //获取真实数据result,等待再次获取数据
        result=sb.toString();
    }

}

FutureData类

在client的调用中,会首先返回一个空的futuredata对象,然后启动一个新的线程去执行业务类获取数据,在获取数据后,会将获取的数据封装进futuredata类中,所以,futuredata类相应的提供了封装实际数据的方法。当你需要获取实际数据当时候,如果尚未获取数据成功,则进入等待队列

public class FutureData implements Data {


    private RealData realData;

    private boolean isReady=false;//如果已经获取数据此处为true

    private ReentrantLock lock=new ReentrantLock();
    private Condition condition=lock.newCondition();

    /**
     * 获取实际数据
     * @return
     */
    @Override
    public String getResult()
    {
        //如果尚未成功获取数据,则当前线程加入等待队列
        while (!isReady){
            try {
                lock.lock();
                condition.await();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }finally {
                lock.unlock();
            }
        }
        return realData.getResult();
    }

    public void setRealData(RealData realData){
        lock.lock();
        if (isReady){
            return;
        }

        //装载实际数据对象
        this.realData = realData;
        isReady = true;
        condition.signal();
        lock.unlock();
    }
}

以上就是future设计模式的简单实现,future模式在线程池的实现中有很大的体现,在第二章中我会详细介绍jdk中futuretask的详细实现,在线程池模块中也会对futureTask的使用作出详细介绍

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值