简单的Future模式及其实现

本文深入探讨了Future模式在多线程设计中的应用,通过生动的蛋糕店比喻,阐述了Future模式的工作原理及其如何简化代码,提高可读性。文章还提供了具体的实现案例,包括自定义实现和使用JDK并发包中的Future类。
摘要由CSDN通过智能技术生成

1 Future模式及实现

Future模式是一个多线程的设计模式,以下一个简单的实现例子。

实现的原理有点类似订蛋糕,你去商店定做蛋糕时,并不能直接拿到蛋糕,而是拿到购物小票之类的,你需要等蛋糕制作完成后,再来取。在这期间你可以去做其他的事情,而不必在蛋糕店等待蛋糕的制作。这和单独开一个线程没有什么区别,具体有什么好处我目前也不是很清楚,能感受到的就是代码更加简洁了…易读性增强了吧~

/**
 * Created by Anur IjuoKaruKas on 2019/10/6.
 * Description :
 */
public class Main {
    public static void main(String[] args) {
        PeopleFutureClient peopleFutureClient = new PeopleFutureClient();
        PeopleFutureContainer peopleFutureContainer = peopleFutureClient.getPeopleFutureContainer("Anur", "女");
        System.out.println(Thread.currentThread().getName() + ":执行接下去的业务");
        System.out.println(Thread.currentThread().getName() + ":" + peopleFutureContainer.getPeople());
    }
}

我们先去蛋糕店,

PeopleFutureClient peopleFutureClient = new PeopleFutureClient();

拿到一张购物小票,店员我们需要一个什么什么样的蛋糕,这个peopleFutureContainer就是一个购物小票。

PeopleFutureContainer peopleFutureContainer = peopleFutureClient.getPeopleFutureContainer("Anur", "女");

然后我们就可以撤了,明天凭购物小票peopleFutureContainer再来拿(getPeople())。

System.out.println(Thread.currentThread().getName() + ":执行接下去的业务");
System.out.println(Thread.currentThread().getName() + peopleFutureContainer.getPeople());

很多网上的例子都是一个接口,然后各种RealData,FutureData,总觉得不是很有必要那么写。下面是我自己的实现方式:

/**
 * Created by Anur IjuoKaruKas on 2019/10/6.
 * Description :
 */
public class PeopleFutureClient {

    public PeopleFutureContainer getPeopleFutureContainer(String name, String sex) {
        PeopleFutureContainer peopleFutureContainer = new PeopleFutureContainer();

        new Thread(new Runnable() {
            @Override
            public void run() {
                peopleFutureContainer.setPeople(new People(name, sex));
            }
        }, "获取信息的线程").start();
        return peopleFutureContainer;
    }
}

蛋糕店,里面就一个取小票的方法

这里直接new了一个小票,并在线程中去执行做蛋糕的方法setPeople,并直接返回了小票。

/**
 * Created by Anur IjuoKaruKas on 2019/10/6.
 * Description :
 */
public class PeopleFutureContainer {

    private People people;
    private boolean isReady = false;

    public synchronized void setPeople(People people) {

        StringBuffer sout = new StringBuffer(Thread.currentThread().getName() + ":获取信息中");
        try {
            for (int i = 0; i < 5; i++) {
                Thread.sleep(1000);
                System.out.println(sout);
                sout.append(".");
            }
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println(Thread.currentThread().getName() + ":获取完成");

        this.people = people;
        isReady = true;
        notify();
    }

    public synchronized People getPeople() {
        if (!isReady) {
            try {
                System.out.println(Thread.currentThread().getName() + ":准备获取信息");
                wait();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
        return people;
    }
}

小票的规则也很简单,就一个set,一个get,都加了锁,这个小票中有一个状态标记isReady,这个的作用相当于电话,你如果没有接到蛋糕店的电话就去取蛋糕了(getPeople),去了以后蛋糕店会告诉你,蛋糕还没做完,等着吧(wait())。等蛋糕做完你才能取走。(比喻不是特别恰当)

当然如果你是等蛋糕做完才来的,那么直接取走就行了,因为这个时候,isReady 已经是ture了,并不需要wait()。

main:执行接下去的业务
main:准备获取信息
获取信息的线程:获取信息中
获取信息的线程:获取信息中.
获取信息的线程:获取信息中..
获取信息的线程:获取信息中...
获取信息的线程:获取信息中....
获取信息的线程:获取完成
main:姓名:Anur,性别:女

执行结果,显而易见,我们来早了,所以“main:准备获取信息”,蛋糕店让我们等着,过了一会儿,我们取到了蛋糕。

想了一下突然发现这样写不如原来的…自己写的这个不符合开放-封闭原则。

补充:

在jdk的Concurrent包中已经有了实现了future模式的类

  final ExecutorService executorService = Executors.newFixedThreadPool(5);

        Callable callable = (() -> {
            System.out.println("请求发送");
            RealData realData = new RealData();
            return realData.getRequest();
        });
        
        Future future = executorService.submit(callable);

        System.out.println("正在做其他事情");
        String result = (String) future.get();
        System.out.println(result);
        executorService.shutdown();

只需要new一个ExecutorService,然后再Callable中去new一个对象并返回,第三步是new一个Future = executorService.submig(callable)

在需要的时候调用future.get方法即可。

最后不要忘记将ExecutorService关闭掉。

正在做其他事情
请求发送
耗时操作
时间============0
时间============1
时间============2
时间============3
时间============4
操作完毕
查询结果

打印结果。

参考来源:https://my.oschina.net/anur/blog/1547017

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值