Future模式在多线程开发中比较常见的设计模式, 其核心思想是异步调用。当我们调用一个函数时,若这个函数执行比较耗时,但调用方并不需要立刻拿到实时的结果时,在需要用到的时候才去调用获取真实的数据或等待,这可以新建一个工作线程去执行,主线程继续往下执行做其它事情。

公共接口

定义一个公共的接口,realData以及futureData都实现该接口

/**
 * FutureData and RealDate implement this interface
 */
public interface Data {
    String getResult();
}

定义RealData

该类定义一个realResult用来表示真是数据

通过在构造函数处sleep 5秒后,才写入this.realResult,模拟一个耗时数据的生产

public class RealData implements Data {

private String realResult;

/**
* 构建函数sleep 5s模拟耗时
*/
public RealData() {
try {
Thread.sleep(5000);
} catch (InterruptedException e) {
e.printStackTrace();
}
this.realResult = "finalData";
}

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

定义FutureData

该类有一个成员变量RealData,和RealData是组合关系,且提供一个set方法装载realData,FutureData实现的接口方法getResult通过调用RealData的getResult方法返回真实数据,相当于封装了一层,其中get和set方法需要使用wait和notify控制,若get时还未拿到真实结果时线程先wait阻塞并释放锁,无论如何,set方法在set完成之后都执行一次notify,唤醒当前对象上的等待线程

public class FutureData implements Data {

    private RealData realData;

    private boolean isReady;

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

    @Override
    public synchronized String getResult() {

        while (!isReady) {
            try {
                wait();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
        return realData.getResult();
    }

    @Override
    public String toString() {
        return "{realData:" + realData + ",isReady:" + isReady + "}";
    }
}

模拟定义一个Client端

/**
 * 模拟client端,有一个query接口实时返回一个futureData,并创建了一个异步工作线程去获取realData然后set入futureData
 */
public class Client {

    public Data query() {
        FutureData futureData = new FutureData();
        //异步装载realData
        new Thread(new Runnable() {
            @Override
            public void run() {
                RealData realData = new RealData();
                futureData.setRealData(realData);
            }
        }).start();
        return futureData;
    }
}

Test Main

测试方法,执行以后可以发现,client端的query接口调用时,拿到的实时结果中realData还是空,主线程调完query接口后仍然可以继续做其它事情,当真正需要用到realData时,调用之前拿到的future结果的getResult方法即可

public class TestMain {

public static void main(String[] args) {

//创建一个客户端
Client client = new Client();
Data currentResult = client.query();

System.out.println("实时查询到的结果:" + currentResult);

System.out.println("main Thread do another things....");

System.out.println("main Thread get RealDateResult:" + currentResult.getResult());
}

}

发表评论

电子邮件地址不会被公开。