多线程设计模式解读—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 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 newInstance() {

    //创建计算任务,传入FutureTask
    final FutureTask futureTask = new FutureTask(new Callable(){
      @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);

你可能感兴趣的:(多线程设计模式解读—Promise(承诺)模式)