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

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

我们先来看一段源码:

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的方式,如:

ExecutorService executorService=Executors.newFixedThreadPool(10);
executorService.execute(futureTask);

原文发布于微信公众号 - java达人(drjava)

原文发表时间:2018-08-12

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏Java与Android技术栈

Java8新的异步编程方式 CompletableFuture(一)

JDK 5引入了Future模式。Future接口是Java多线程Future模式的实现,在java.util.concurrent包中,可以来进行异步计算。

25910
来自专栏向治洪

android classloader双亲委托模式

概述 ClassLoader的双亲委托模式:classloader 按级别分为三个级别:最上级 : bootstrap classLoader(根类加载器) ;...

29180
来自专栏小勇DW3

LockSupport的源码实现原理以及应用

如果只是LockSupport在使用起来比Object的wait/notify简单,

32120
来自专栏吴伟祥

四种任务调度的 Java 实现 转

 java.util.Timer 了,它是最简单的一种实现任务调度的方法,下面给出一个具体的例子:

17110
来自专栏微信公众号:Java团长

Java里如何实现线程间通信?

假设有两个线程,一个是线程 A,另一个是线程 B,两个线程分别依次打印 1-3 三个数字即可。我们来看下代码:

12410
来自专栏xingoo, 一个梦想做发明家的程序员

AngularJS 中的Promise --- $q服务详解

先说说什么是Promise,什么是$q吧。Promise是一种异步处理模式,有很多的实现方式,比如著名的Kris Kwal's Q还有JQuery的Deffe...

19990
来自专栏Java进阶之路

使用CompletionService非阻塞获取多线程返回值

Future接口是Java标准API的一部分,在java.util.concurrent包中。Future接口是Java线程Future模式的实现,可以来进行异...

14620
来自专栏高爽的专栏

Java线程(七):Callable和Future

       接着上一篇继续并发包的学习,本篇说明的是Callable和Future,它俩很有意思的,一个产生结果,一个拿到结果。        Calla...

20400
来自专栏haifeiWu与他朋友们的专栏

FutureTask源码分析

FutureTask:一个可取消的异步任务执行类,这个类提供了Future接口的基本实现,主要有以下功能:

18230
来自专栏无题

JAVA多线程构件(java.util.concurrent包下高级工具)

Java1.5提供了一个非常高效实用的多线程包:java.util.concurrent, 提供了大量高级工具,可以帮助开发者编写高效、易维护、结构清晰的Jav...

1.3K80

扫码关注云+社区

领取腾讯云代金券