24 future模式

1 引入

比如说我们调用一些方法的的时候,这个方法执行的时间比较长,如果是同步调用的化的就会调用方就会因为这个被调用方阻塞。
比如说我们去定生日蛋糕的时候,我们可以同步等待蛋糕制作完成带走蛋糕,也可以先去处理别的事情比如逛逛周边的商场等,等到差不多的时候回去取蛋糕带走

eg:

package study.wyy.concurrency.future;

public class SyncInvoker {

    public static void main(String[] args) throws InterruptedException {
        String result = get();
        System.out.println(result);
        doOther();
    }

    private static void doOther() {
        System.out.println("do other thing....");
    }

    private static String get() throws InterruptedException {
        // 模拟get方法执行的耗时
        Thread.sleep(10000L);
        return "FINSH";
    }
}

main方法只有等到get方法执行完毕才会去执行doOther()

2 Future模式

Future模式简单来说说调用方可以先去处理别的事情,在未来的某个时间去那之前被调用方的结果。

package study.wyy.concurrency.future;


/**
* @Description 封装返回给调用的的结果, 泛型T就是结果
*
* @Author  wyaoyao
* @Date   2020/9/6 10:14 下午
* @Param
* @Return
* @Exception
 *
*/
public interface Future<T>{

    /**
     *  @author: wyaoyao
     *  @Date: 2020/9/6 10:32 下午
     *  @Description: 提供一个方法,让调用方通过这个来拿调用结果
     */
    T get() throws InterruptedException;

    /**
     *  @author: wyaoyao
     *  @Date: 2020/9/6 10:34 下午
     *  @Description: 当任务执行完毕,将结果通知Future
     */
    void done(T result);
}

package study.wyy.concurrency.future;


/**
* @Description: 任务,封装真正的执行的逻辑
* @Author  wyaoyao
* @Date   2020/9/6 10:16 下午
* @Param    
* @Return      
* @Exception   
*/
public interface FutureTask<T> {


    /**
    * @Description 封装真正的执行的逻辑
    * @Author  wyaoyao
    * @Date   2020/9/6 10:16 下午
    * @Param
    * @Return
    * @Exception
    */
    T call();
}

package study.wyy.concurrency.future;

/**
* @Description 将Future和FutureTask桥接起来
* @Author  wyaoyao
* @Date   2020/9/6 10:18 下午
* @Param
* @Return
* @Exception
*/
public class FutureService {

    /**
     *  @author: wyaoyao
     *  @Date: 2020/9/6 10:18 下午
     *  @Description: 提交任务
     */
    public <T> Future<T> submit(final FutureTask<T> task){
        // new AsyncFuture,返回给调用方
        Future<T> future = new AsyncFuture<>();
        // 开启一个线程去执行本次的任务(异步)
        new Thread(()->{
            // 执行逻辑
            T result = task.call();
            // 执行完毕,通知给future
            future.done(result);

        }).start();
        return future;
    }
}

package study.wyy.concurrency.future;


/**
* @Description 异步的实现
* @Author  wyaoyao
* @Date   2020/9/6 10:20 下午
* @Param
* @Return
* @Exception
*/
public class AsyncFuture<T> implements Future<T>{

    /**
     *  @Description: 是否已经执行完
     */
    private volatile  boolean isDone = false;

    private T result;
    @Override
    public T get() throws InterruptedException {
        synchronized (this){
            while (!isDone){
                // 如果还没有完成,外部(调用方)想通过这个方法拿执行结果,肯定是不能让拿的,所以等待
                this.wait();
            }
        }
        // 完成的话,就返回结果
        return result;
    }

    /**
     *  @author: wyaoyao
     *  @Date: 2020/9/6 10:34 下午
     *  @Description: 当任务执行完毕,将结果通知Future
     */
    @Override
    public void done(T result){
        synchronized (this){
            this.result = result;
            this.isDone = true;
            // 唤醒线程
            this.notifyAll();
        }
    }
}

package study.wyy.concurrency.future;

public class AsyncFutureTest {

    public static void main(String[] args) throws InterruptedException {
        FutureService futureService = new FutureService();
        Future<String> future = futureService.submit(() -> {
            // 模拟方法执行的耗时
            try {
                Thread.sleep(10000L);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            return "FINSH";
        });
        // 干其他事情去了
        doOther();
        // 其他事情做完了,我来取刚刚的结果(蛋糕)
        String result = future.get();
        System.out.println(result);


    }

    private static void doOther() throws InterruptedException {
        System.out.println("do other thing....");
        // 模拟方法执行的耗时
        Thread.sleep(1000L);
    }
}

3 总结

角色

  • Future: 代表的是未来的一个凭据
  • FutureTask:将调用逻辑进行了隔离
  • FutureService:桥接Future和FutureTask

4 改进:加入CallBack

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-GfuQwPuO-1599899882146)(evernotecid://FA2713E9-40BE-49E5-BF9D-E3ACD77E4128/appyinxiangcom/21741088/ENResource/p599)]

这里完全可以使用java8 提供的consumer这个函数式接口,不需要自己去定义一个接口。

package study.wyy.concurrency.future;

import java.util.function.Consumer;

/**
* @Description 将Future和FutureTask桥接起来
* @Author  wyaoyao
* @Date   2020/9/6 10:18 下午
* @Param
* @Return
* @Exception
*/
public class FutureService {

    /**
     *  @author: wyaoyao
     *  @Date: 2020/9/6 10:18 下午
     *  @Description: 提交任务
     */
    public <T> Future<T> submit(final FutureTask<T> task){
        // new AsyncFuture,返回给调用方
        Future<T> future = new AsyncFuture<>();
        // 开启一个线程去执行本次的任务(异步)
        new Thread(()->{
            // 执行逻辑
            T result = task.call();
            // 执行完毕,通知给future
            future.done(result);

        }).start();
        return future;
    }


    /**
     *  @author: wyaoyao
     *  @Date: 2020/9/6 10:18 下午
     *  @Description: 提交任务
     */
    public <T> Future<T> submit(final FutureTask<T> task, Consumer<T> consumer){
        // new AsyncFuture,返回给调用方
        Future<T> future = new AsyncFuture<>();
        // 开启一个线程去执行本次的任务(异步)
        new Thread(()->{
            // 执行逻辑
            T result = task.call();
            // 执行完毕,通知给future
            future.done(result);
            // 执行完毕,交给回调
            consumer.accept(result);

        }).start();
        return future;
    }
}

 public static void main(String[] args) throws InterruptedException {
        FutureService futureService = new FutureService();
        Future<String> future = futureService.submit(() -> {
            // 模拟方法执行的耗时
            try {
                Thread.sleep(10000L);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            return "FINSH";
        },s->{
            System.out.println(s);
        });
        // 干其他事情去了
        doOther();


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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值