博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
[面试]future模式
阅读量:4635 次
发布时间:2019-06-09

本文共 4217 字,大约阅读时间需要 14 分钟。

Future模式

什么是future模式?

传统单线程环境下,调用函数是同步的,必须等待程序返回结果后,才可进行其他处理。 Futrue模式下,调用方式改为异步。

Futrue模式的核心在于:充分利用主函数中的等待时间,利用等待时间处理其他任务,充分利用计算机资源。

简单描述一下future模式的实现

future模式有两种数据, 一种是真实数据RealData, 里面就是业务中想要得到的目标数据. 另一种是虚拟数据FutureData, 它是在使用future模式时立即返回的一个对象. 

调用方会首先拿到一个FutureData, 然后调用方就认为自己拿到该数据了, 没有进行阻塞, 继续去执行下面的逻辑处理. 如果真实数据准备好了, 就会把自己的引用赋给之前的那个FutureData, 并且置一个标记, 表示这个FutureData里面包含一个RealData, 拿到了想要的数据, 可以使用.

详细分的话, 会有下面这几种情况(假设RealData需要2秒才能创建好):

1. 调用方发送了自己需要RealData的请求的后, 会立即拿到一个FutureData, 但是根本就不着急使用, 所以, 第2秒的时候RealData创建完成后, 就会被绑定到对应的FutureData里. 假设第6秒调用方才开始使用RealData, 他会发现FutureData已经准保好了他想要的数据, 于是开心地使用就ok了.

2. 调用方发送了自己需要RealData的请求的后, 会立即拿到一个FutureData, 但是很着急使用, 因为接下来的处理过程依赖于RealData的内容. 于是在第0.5秒的时候, 调用方就想要获取RealData. 但是这个时候RealData并没有准备好, 此时的FutureData是一个空壳而已. 所以就在这里进行wait(或者忙等待). 直到RealData准备好,也就是再过1.5秒, 线程才会唤醒(或者打破忙等待).

请用代码实现一下Future模式

FutureData和RealData的统一抽象接口, Data类如下:

public interface Data {    int getResult() throws InterruptedException;}

RealData类

public class RealData implements Data {    private int data;    public RealData(int num) {        //这里用sleep来模拟构造一个复杂对象的场景        try {            Thread.sleep(2000);        } catch (InterruptedException e) {            e.printStackTrace();        }                this.data = num * 10;    }    @Override    public int getResult() {        return data;    }}

FutureData类

public class FutureData implements Data {    // 真实数据RealData的引用.    private RealData realData = null;    public synchronized void setRealData(RealData realData) {        // 如果this.realData不是空, 说明已经准备好了, 直接return        if (this.realData != null)            return;        this.realData = realData;        notifyAll();    }    @Override    public synchronized int getResult() throws InterruptedException {        // 如果this.realData是null, 说明数据还没准备好, 应该等待        if (this.realData == null) {            wait();        }        return realData.getResult();    }}

Client类

直接创建一个FutureData, 然后直接返回这个FutureData. 同事开辟一个线程来创建RealData, 并且在RealData创建完后绑定在FutureData中.

public class Client {    public Data request(final int num) {        // 当有请求的时候, 先创建一个虚拟对象.        final FutureData futureData = new FutureData();        // 然后开启一个新线程去创建RealData, 当RealData创建完成后, 绑定带FutureData里.        new Thread(() -> {            RealData realData = new RealData(num);            futureData.setRealData(realData);        }).start();        // 不管RealData有没有创建完成, 都会直接返回这个FutureData.        return futureData;    }}

Main

调用这个Future模型.

public class Main {    public static void main(String[] args) throws InterruptedException {        Client client = new Client();        // 调用了之后会立即返回一个FutureData, 这个data就是FutureData        Data data = client.request(4);        // 用sleep来模拟主线程正在处理其他事情        Thread.sleep(0);        // getResult来获取真实数据        //     |- 如果这时候真实数据没准备好, 那么就wait, 等待notify, 然后获取到真实数据        //     |- 如果这时候真实数据准备好了, 那么就可以直接获取到了        System.out.println("数据=" + data.getResult());    }}

 在RealData处进行了*10 的处理, 所以request(4), 最终会返回40.

使用过JDK自带的Future模式吗?

使用过, 例子如下:

定义一个RealData类

import java.util.concurrent.Callable;public class RealData implements Callable
{ private int data; public RealData(int data) { this.data = data * 10; } @Override public Integer call() { //利用sleep方法来表示真是业务是非常缓慢的 try { Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } return data; }}

 Main

import java.util.concurrent.ExecutorService;import java.util.concurrent.Executors;import java.util.concurrent.FutureTask;public class Main {    public static void main(String[] args) throws Exception {        //线程池        ExecutorService executor = Executors.newFixedThreadPool(1); //使用线程池        // 之前自己实现的future模式中的 Data data = client.request(4) 这句相当于下面这两行代码        //1. Data data        FutureTask
futureTask = new FutureTask<>(new RealData(4)); //2. 这里相当于 client.request(4); executor.submit(futureTask); //这里可以用一个sleep代替对其他业务逻辑的处理 Thread.sleep(0); // 获取真实数据 try { System.out.println("数据=" + futureTask.get()); }finally { executor.shutdown(); } }}

 

转载于:https://www.cnblogs.com/noKing/p/9244818.html

你可能感兴趣的文章
installshield 注册dll
查看>>
京华同学聚会
查看>>
JSP--JavaBean
查看>>
成功将BlogEngine 1.5 升级到了BlogEngine 2.0
查看>>
【shell】创建长目录,目录存在则忽略,缺失则创建
查看>>
个人随笔、收藏——(包括技术、设计思想等)
查看>>
第一段冲刺_个人总结_5.2
查看>>
Usage and Idioms——Categories
查看>>
一: 建立Vue sampleproject
查看>>
数据结构之shell排序
查看>>
CodeForces 375D Tree and Queries
查看>>
牛客~~打篮球~~~模拟水题
查看>>
LeetCode-198. 打家劫舍
查看>>
5 -- Hibernate的基本用法 --2 1 Hibernate 下载和安装
查看>>
Socket
查看>>
【C#公共帮助类】10年代码,最全的系统帮助类
查看>>
JQuery UI
查看>>
张弛有度
查看>>
【ZJOI2008】树的统计(树链剖分)
查看>>
【NOIP校内模拟】T2 华莱士(环套树)
查看>>