Callable和FutureTask,模拟实现机制

前言

常用创建线程方式有Thread,Runable还有就是Callable,前面两者执行完之后无法返回结果,Callable提供执行线程完毕之后,可以获取结果机制,需要Future一起使用。今天以一个简单的案例来模拟实现机制。

场景描述

在一个阳光明媚的周末,一觉醒来以然是中午了,做饭时万万不可能的,所以需要订外卖咯,但是此时短信提醒又有快递需要去取,所以就出现了以下的常规操作,先定外卖,再去快递,取完快递回来接受外卖,最后享受午餐。
在这里插入图片描述

通过Callable实现

public static void main(String[] args) throws ExecutionException, InterruptedException {
        Callable<String> callable = new Callable<String>() {
            @Override
            public String call() throws Exception {
                log.info("lk在" + DateUtil.timeFormat(new Date()) + "时间下单成功!预约发货时间为:2019-06-02 13:00:00");
                try {
                    //模拟制作过程
                    Thread.sleep(5000);
                    log.info("制作完成,准备发货...");
                } catch (InterruptedException e) {
                    log.error("制作出错!",e);
                }
                return "{订餐名称='全家桶', 到达时间=2019-06-02 13:00:00}";
            }
        };

        FutureTask<String> task = new FutureTask<>(callable);
        Thread thread = new Thread(task);
        thread.start();
        log.info("先去取快递...");

        log.info("回来了,饭也到了,"+ task.get());
    }

模拟底层实现机制完成场景

Person就是我,需要订单和取快递的那个

@Slf4j
public class Person {
    public static void main(String[] args) {
        Order order = ProductFactory.instance().createProduce("全家桶","lk",
                DateUtil.formatTime("2019-06-02 13:00:00"));
        log.info("先去取快递...");
        log.info("回来了,饭也到了,"+ order.getProduct());
    }
}

外卖制作者

@Slf4j
public class Product {
    /**
     * 用户名
     */
    private String userName;
    /**
     * 外卖名称
     */
    private String name;
    /**
     * 下单时间
     */
    private Date orderTime;
    /**
     * 送达时间
     */
    private Date deliveryTime;

    public Product(String name, String userName, Date deliveryTime,Date orderTime) {
        this.orderTime = orderTime;
        this.name = name;
        this.userName = userName;
        this.deliveryTime = deliveryTime;
        try {
            //模拟制作过程
            Thread.sleep(5000);
            log.info(name + "制作完成,准备发货...");
        } catch (InterruptedException e) {
            log.error("制作出错!",e);
        }
    }

    @Override
    public String toString() {
        return "{" +
                "订餐名称='" + name + '\'' +
                ", 到达时间=" + DateUtil.timeFormat(deliveryTime) +
                '}';
    }
}

商家

@Slf4j
public class ProductFactory {

    private static volatile ProductFactory factory;

    public Order createProduce(String name, String userName, Date deliveryTime){
        Date orderTime = new Date();
        log.info(userName + "在" + "2019-06-01 12:20:00" + "时间下单成功!预约发货时间为:" + DateUtil.timeFormat(deliveryTime));
        Order order = new Order();
        new Thread(new Runnable() {
            @Override
            public void run() {
                Product product = new Product(name,userName,deliveryTime,orderTime);
                order.setProduct(product);
            }
        }).start();

        return order;
    }

    private ProductFactory() {}

    public static ProductFactory instance(){
        if (factory == null){
            synchronized (ProductFactory.class){
                if (factory == null){
                    factory = new ProductFactory();
                }
            }
        }
        return factory;
    }
}

订单

@Slf4j
public class Order {
    private Product product;

    private boolean complete = false;

    public synchronized Product getProduct() {
        while (!complete){
            try {
                wait();
            } catch (InterruptedException e) {
                log.error("异常了!",e);
            }
        }
        return product;
    }

    public synchronized void setProduct(Product product) {
        if (complete){
            return;
        }
        this.product = product;
        complete = true;
        notifyAll();
    }
}

执行main即可

机制分析

其中FutureTask其实对应的就是Order,Callable对应Product和ProducetFactory。
通过wait和notifyAll机制模拟阻塞获取结果集,如果看Future的实现机制,会发现是通过WaitNode对象和一些状态信息来实现的,比较关键的两个方法set和get方法分别对应Order中的setProduct和getProduct。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值