前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >多线程设计模式解读2—Promise(承诺)模式

多线程设计模式解读2—Promise(承诺)模式

作者头像
java达人
发布2018-08-20 14:22:07
6320
发布2018-08-20 14:22:07
举报
文章被收录于专栏:java达人java达人

上次我们讲到多线程设计模式的Guarded Suspension(保护性暂挂模式),Guarded Suspension是条件未满足时线程一直处于等待状态,直到条件满足才继续运行,而在Promise模式中,Promise的getResult方法获取异步任务结果,如果任务未执行完毕,就一直处于等待状态,可以说,Promise模式是Guarded Suspension模式的一个应用实例,它有两个重要角色:Promise,主要用于包装异步任务处理结果;Promisor,用于对外提供返回Promise的异步方法,并启动异步任务。而这里Promise可以直接用JDK 中的Future实现。

我们先来看一段源码:

代码语言:javascript
复制
public class FutureTaskMain {

  public static void main(String[] args){

    //初始化长时计算器
    Future<Integer> calculatorPromise = Calulator.newInstance();
    System.out.println("模拟主线程任务执行开始...");
    System.out.println("模拟主线程任务执行结束...")
  //获取执行结果,
    try {
  //异步操作被封装在了Calculator中
      Integer result = (Integer) calculatorPromise.get(6, TimeUnit.SECONDS);
      System.out.println("长时任务执行完成,结果:"+result);
    } catch (InterruptedException e) {
//     守护线程阻塞被打断;
      e.printStackTrace();
    } catch (ExecutionException e) {
//      执行任务时出错;
      e.printStackTrace();
    } catch (TimeoutException e) {
//     执行超时
      calculatorPromise.cancel(true);
      e.printStackTrace();
    } catch (CancellationException e) {
      //如果线程已经cancel了,再执行get操作会抛出这个异常
      e.printStackTrace();
    }

  }

}



class Calulator{
  public static Future<Integer> newInstance() {

    //创建计算任务,传入FutureTask
    final FutureTask futureTask = new FutureTask(new Callable<Integer>(){
      @Override
      public Integer call() throws Exception {
        System.out.println("模拟长时间计算任务执行中...");
        Thread.sleep(5000);
        Random rand = new Random();
        Integer i = rand.nextInt(900) + 100;
        return i;
      }
    });


    new Thread(futureTask).start();

    return futureTask;
  }
}

这里FutureTask就是Promise角色,主要用于包装异步任务处理结果,而Calculator是Promisor角色,我们可以看到,Promise模式屏蔽了同步和异步编程的差异,异步操作被封装在了Calculator中,客户端代码像调用同步方法一样直接调用即可,无需关注内部的技术细节。

有两个需要注意的地方:

1、异常的处理

你希望知道Promise执行过程中是否会抛出异常,而它是运行在异步方法中的,Promisor方法并不知道,解决方法是将异常记录在Promise的实例变量中,在返回时检查抛出,不过FutureTask已经帮我们实现了这一步,我们只要处理get返回时抛出的异常即可。

2、访问过多时会产生大量的线程,增加系统的开销和资源的消耗,因此,可以考虑用FutureTask + ExecutorService的方式,如:

代码语言:javascript
复制
ExecutorService executorService=Executors.newFixedThreadPool(10);
executorService.execute(futureTask);

本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2018-08-12,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 java达人 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档