Promise-在Java中以同步的方式异步编程

java Promise

java promise(GitHub)是Promise A+规范的java实现版本。Promise A+是commonJs规范提出的一种异步编程解决方案,比传统的解决方案—回调函数和事件—更合理和更强大。promise实现了Promise A+规范,包装了java中对多线程的操做,提供统一的接口,使得控制异步操做更加容易。实现过程当中参考文档以下:java

基本使用:git

<repositories>
    <repository>
      <id>wjj-maven-repo</id>
      <url>https://raw.github.com/zhanyingf15/maven-repo/master</url>
    </repository>
</repositories>
复制代码
<dependency>
  <groupId>com.wjj</groupId>
  <artifactId>promise</artifactId>
  <version>1.0.0</version>
</dependency>
复制代码
IPromise promise = new Promise.Builder().promiseHanler(new PromiseHandler() {
    @Override
    public Object run(PromiseExecutor executor) throws Exception {
        return 2*3;
    }
}).build();

复制代码

上面的例子中建立了一个promise对象,指定PromiseHandler实现,在run方法中写具体的业务逻辑,相似于Runable的run方法。promise对象一经建立,将当即异步执行。推荐使用lambda表达式,更加简洁。es6

IPromise promise = new Promise.Builder().promiseHanler(executor -> {
    return 2*3;
}).build();
复制代码

获取promise的执行结果一般使用两个方法thenlisten,前者是阻塞的后者是非阻塞的。then方法返回一个新的promise对象,所以支持链式调用。github

new Promise.Builder().promiseHanler(executor -> {//promise0
    return 2*3;
}).build().then(resolvedData -> {//返回一个新的promise1
    System.out.println(resolvedData);
    return (Integer)resolvedData+1;
}).then(res2->{
    System.out.println(res2);
    //建立一个新的promise2并返回
    return new Promise.Builder().externalInput(res2).promiseHanler(executor -> {
        return (Integer)executor.getExternalInput()+2;
    }).build();
}).then(res3->{
    System.out.println(res3);
    return res3;
});
复制代码

从上面能够看到promise0、promise1和Promise2是链式调用的,每一次then方法都返回一个新的promise。在then方法的回调中,若是返回的是一个非promise对象,那么promise被认为是一个fulfilled状态的promise,若是返回的是一个promsie实例,那么该实例将会异步执行。
假如须要异步顺序执行a->b-c->d四个线程,调用顺序以下编程

new PromiseA()
.then(dataA->new PromiseB())//A的回调
.then(dataB->new PromiseC())//B的回调
.then(dataC->new PromiseD())//C的回调
.then(dataD->xxx)//D的回调
.pCatch(error->xxxx)//捕获中间可能产生的异常
复制代码

具体使用 方式参考promise-java异步编程解决方案数组

Docs

promise规范

promise规范能够参考 Promise A+规范。其中ES6 Promise对象 在Promise A+规范上作了一些补充。java promise在使用上基本与ES6 Promise对象保持一致,部分地方有些许不一样,后面会作出说明。 Promise的三个状态promise

  • pending:等待态,对应线程未执行或执行中
  • fulfilled:完成态,对应线程正常执行完毕,其执行结果称为终值
  • rejected:拒绝态,对应线程异常结束,其异常缘由称为拒因
    状态转移只能由pending->fulfilled或pending->rejected,状态一旦发生转移没法再次改变。

Promise

Promise是IPromise的实现,Promise实例一经建立,将当即异步执行,部分接口以下bash

IPromise then(OnFulfilledExecutor onFulfilledExecutor)
  • 若是当前promise处于pending状态,阻塞当前线程,等待promise状态转变为fulfilled或rejected
  • 若是处于fulfilled状态,执行onFulfilledExecutor.onFulfilled(resolvedData)回调。
    • 若是回调返回一个Promise对象a,以a做为then方法的返回值,若是回调返回一个普通对象obj,以obj做为终值、状态为fulfilled包装一个新Promise做为then方法的返回值
    • 若是执行回调过程当中产生异常e,返回一个以e做为拒因、状态为rejected的新Promise,并拒绝执行接下来的全部Promise直到遇到pCatch。
  • 若是处于rejected状态,执行onRejectedExecutor.onRejected(rejectReason)回调,返回一个以当前promise的异常做为拒因、状态为rejected的新Promise,并拒绝执行接下来的全部Promise直到遇到pCatch或pFinally
    参数:

IPromise pCatch(OnCatchedExecutor onCatchedExecutor);

then(null,onRejectedExecutor)的别名,但返回不一样于then,出现异常时能够选择不拒绝接下来Promise的执行,可用于异常修正,相似于try{}catch{}
该方法会尝试捕获当前promise的异常,最终返回一个新Promise,当被捕获Promise处于不一样的状态时有不一样的行为多线程

  • pending:阻塞当前线程,等待pending转变为fulfilled或rejected,行为同then
  • fulfilled:不执行回调,以当前Promise终值和状态返回一个全新的Promise
  • rejected:执行onCatched(Throwable catchReason)回调。
    • 若是onCatched方法返回一个Promise,以这个Promise做为最终返回。
    • 若是onCatched方法返回一个非Promise对象obj,以obj做为终值、fulfilled状态返回一个全新的对象。
    • 若是执行回调过程当中产生异常e,以e为拒因、状态为rejected返回一个新的Promise,并拒绝执行接下来的全部Promise直到再次遇到pCatch
void listen(OnCompleteListener onCompleteListener);

指定一个监听器,在promise状态转为fulfilled或rejected调用,该方法不会阻塞线程执行,能够屡次调用指定多个监听器异步

void pFinally(OnCompleteListener onCompleteListener);

listen的别名,行为同listen

Status getStatus()

获取promise的当前状态

Object getResolvedData()

获取promise fulfilled状态下的终值,其他状态下时为null

Throwable getRejectedData()

获取promise rejected状态下的拒因,其他状态下为null

Future getFuture()

获取promise对应异步任务的future

boolean cancel()

尝试取消promise对应的异步任务,底层调用future.cancel(true)。fulfilled或rejected状态下无效。

Promise.Builder

Promise对象生成器

Builder pool(ExecutorService threadPool)

指定一个线程池用于执行promise任务,若是不指定,每个promise都将启动一个线程

Builder promiseHanler(PromiseHandler promiseExecutor)

指定promise执行器,在promiseHanler的run方法中实现线程的具体业务逻辑,注意==promise对象一经建立,将当即执行其中的逻辑==

Builder externalInput(Object externalInput)

向Promise注入一个外部参数,能够在指定PromiseHandler时经过PromiseExecutor.getExternalInput()获取

int i = 3;
IPromise p = new Promise.Builder()
.externalInput(i).promiseHanler(new PromiseHandler() {
    public Object run(PromiseExecutor executor) {
        Integer args = (Integer) executor.getExternalInput();
        return args*2;
    }
}).build();
复制代码
Builder promise(IPromise promise)

指定一个promise x,使当前promise接受 x 的状态

  • 若是 x 处于pending, 当前promise 需保持为pending直至 x 转为fulfilled或rejected
  • 若是 x 处于fulfilled,用x的终值值执行当前promise,能够在指定PromiseHandler时经过PromiseExecutor.getPromiseInput()获取
  • 若是 x 处于拒绝态,用相同的据因拒绝当前promise执行
ExecutorService fixedPool = Promise.pool(1);
IPromise promise1 = new Promise.Builder().pool(fixedPool).promiseHanler(executor->3).build();
IPromise promise2 = new Promise.Builder().pool(fixedPool)
    .promise(promise1)
    .promiseHanler(executor->4+(Integer) executor.getPromiseInput())
.build()
.then(resolvedData->{
    System.out.println(resolvedData);
    return resolvedData;
}, rejectedReason-> rejectedReason.printStackTrace());
复制代码

最终结果返回7,。若是promise1在执行过程当中抛出异常e,promise2将被拒绝执行,将会以e做为拒因,状态为rejected返回一个新的Promise,最终会执行rejectedReason-> rejectedReason.printStackTrace()回调。

IPromise build()

建立一个Promise实例

Promise的静态方法

static IPromise all(IPromise ...promises)

将多个 Promise 实例p1,...pn,包装成一个新的 Promise 实例 p,只有当p1-pn的状态都转为fulfilled时,p的状态才为fulfilled,此时p1-pn的返回值包装为一个数组Object[r1,...rn]做为p的终值。
只要p1-pn中任意一个被rejected,p的状态就转为rejected,将第一个被rejected的promise的拒因做为p的拒因,并尝试取消其他promise的执行(内部调用future.cancel(true))

static IPromise race(IPromise ...promises)

将多个 Promise p1,...pn实例,包装成一个新的 Promise 实例 p,只要p1-pn有一个状态发生改变,p的状态当即改变。并尝试取消其他promise的执行(内部调用future.cancel(true))
第一个改变的promise的状态和数据做为p的状态和数据

static IPromise resolve()

建立一个终值为null、fulfilled状态的promise

static IPromise resolve(Object object)

建立一个终值为object、fulfilled状态的promise

static IPromise resolve(Object object,List args)

将object的then方法以异步方式执行,then方法的执行结果做为Promise的终值

static IPromise resolve(Object object,String methodName,List args)

将object的指定方法以异步方式执行,该方法的执行结果做为Promise的终值,目标方法的参数必须按顺序包含在List中,如object.doSomething(int a,Map b),用resolve执行为

List args = new ArrayList()
args.add(1);
args.add(map)
Promise.resolve(object,"doSomething",args);
复制代码
static IPromise reject(Object reason)

建立一个拒由于reason、rejected状态的promise

static IPromise pTry(Object object,String methodName,List args)

将object的指定方法以同步方式执行,该方法的执行结果做为Promise的终值,若是object为IPromise实例,将忽略methodName和args参数,异步执行该实例。
该方法是以Promise统一处理同步和异步方法,无论object是同步操做仍是异步操做,均可以使用then指定下一步流程,用pCatch方法捕获异常,避免开发中出现如下状况

try{
  object.doSomething(args1,args2);//可能会抛出异常
  promise.then(resolvedData->{
      //一些逻辑
  }).then(resolvedData->{
      //一些逻辑
  }).pCatch(e->{
      //异常处理逻辑
  })
}catch(Exception e){
  //异常处理逻辑
}
复制代码

使用pTry,能够简化异常处理

List args = new ArrayList(){args1,args2};
Promise.pTry(object,"doSomething",args)
.then(resolvedData->{
      //一些逻辑
}).then(resolvedData->{
  //一些逻辑
}).pCatch(e->{
  //异常处理逻辑
})
复制代码

PromiseHandler

定义异步逻辑的接口

Object run(PromiseExecutor executor)throws Exception;

run方法中实现具体的业务逻辑,最终run方式是在线程的call方法执行,若是run方法中含有wait、sleep...等锁操做,可能须要自行处理InterruptedException。由于该线程可能被外部调用cancel()或interrupt()方法

PromiseExecutor

promise状态处理

void resolve(final Object args)

将Promise对象的状态从“未完成”变为“成功”(即从pending变为fulfilled)。注意该方法一经调用,promise状态将不可改变,以下例,在调用executor.resolve(3);后,return以前抛出一个异常,promise的状态依旧是fulfilled,终值为3。

new Promise.Builder().promiseHanler(new PromiseHandler(){
    @Override
    public Object run(PromiseExecutor executor) {
        executor.resolve(3);
        throw new RuntimeException("error");
        return null;
    }
}).build()
复制代码

在run方法中executor.resolve(3)等同于return 3

@Override
public Object run(PromiseExecutor executor) {
    return 3;
}
复制代码

大多数状况下建议直接使用return返回promise的终值。

void reject(final Throwable args)

将Promise对象的状态从“未完成”变为“失败”(即从pending变为fulfilled)

Object getExternalInput()

获取经过new Promise.Builder().externalInput(Object externalInput)方法注入的参数,具体参考Promise.Builder#externalInput(Object externalInput)

Object getPromiseInput()

获内部promise的执行结果。经过new Promise.Builder().promise(promise1)指定的promise1的执行结果。具体参考 Promise.Builder#promise(IPromise promise)

OnFulfilledExecutor

fulfilled回调接口

Object onFulfilled(Object resolvedData)throws Exception;

状态转为fulfilled时的回调,返回值能够是IPromise实例或普通对象。若是object是IPromise实例,object做为then方法的返回值,若是object是个普通对象,以object做为终值、状态为fulfilled包装一个新Promise做为then方法的返回值

OnRejectedExecutor

rejected回调接口

void onRejected(Throwable rejectReason)throws Exception;

当Promise转变为rejected状态时的回调

OnCatchedExecutor

rejected回调接口

Object onCatched(Throwable catchReason)throws Exception;

当发生异常时的回调,最终返回一个Promise或普通对象,若是是一个普通对象,这个对象将做为下一个Promise的终值

OnCompleteListener

void listen(Object resolvedData,Throwable e);

当Promise执行结束时的回调(不管是fulfilled仍是rejected)

  • resolvedData fulfilled状态时的终值,rejected状态时为null
  • e rejected状态时的异常信息,fulfilled状态时为null

示例

示例1:基本使用
new Promise.Builder().promiseHanler(new PromiseHandler(){
    @Override
    public Object run(PromiseExecutor executor) {
        executor.resolve(3);//返回异步执行结果3
        return null;
    }
}).build().then(new OnFulfilledExecutor() {
    @Override
    public Object onFulfilled(Object resolvedData) {
        Integer i = ((Integer)resolvedData)+1;//获取上一个promsie执行结果3,执行+1
        System.out.println(i);//输出执行结果4
        //建立一个新的promise,将4做为该promise的输入
        IPromise p = new Promise.Builder().externalInput(i).promiseHanler(new PromiseHandler() {
            @Override
            public Object run(PromiseExecutor executor) {
                //获取外部输入4
                Integer args = (Integer) executor.getExternalInput();
                executor.resolve(args*2);//执行 4x2
                return null;
            }
        }).build();
        return p;//返回该promise p
    }
})
.then(new OnFulfilledExecutor() {//执行p的回调
    @Override
    public Object onFulfilled(Object args) {
        System.out.println(args);//输出p的执行结果
        return args;
    }
}, new OnRejectedExecutor() {//捕获可能出现的异常
    @Override
    public void onRejected(Throwable rejectedReason) throws Exception {
        rejectedReason.printStackTrace();
    }
});
复制代码

结果

4
8
复制代码
示例2
ExecutorService fixedPool = Promise.pool(1);//建立一个线程池
//建立promise1
IPromise promise1 = new Promise.Builder().pool(fixedPool).promiseHanler(executor->3).build();
//建立promise2
IPromise promise2 = new Promise.Builder().pool(fixedPool)
    .promise(promise1)//让promise2接受promise1的状态,优先执行promise1
    .promiseHanler(executor->{
        //获取promise1的执行结果,执行promise2的逻辑
        return 4+(Integer) executor.getPromiseInput();
    })
    .build()
    .then(resolvedData->{
        System.out.println(resolvedData);//打印promise2的执行结果 
        return resolvedData;
    }, rejectedReason-> rejectedReason.printStackTrace());
System.out.println("end");
fixedPool.shutdown();
复制代码

结果

7
end
复制代码
示例3:错误处理
new Promise.Builder().promiseHanler(executor -> 3).build().then(resolvedData->{
    System.out.println("a:"+resolvedData);
    return new Promise.Builder().promiseHanler(executor -> {
        executor.reject(new RuntimeException("err"));//抛出异常
        return null;
    }).build();
}).then(resolvedData1 -> {//fulfilled回调
    System.out.println("b:"+resolvedData1);
    return resolvedData1;
},rejectReason -> {//rejected回调
    System.err.println("c:"+rejectReason);
});
复制代码

结果

a:3
c:java.lang.RuntimeException: err
复制代码
示例4:pCatch
new Promise.Builder().promiseHanler(executor -> 0).build()
  .then(res0->{
    System.out.println("a:"+res0);//输出 a:0
    Thread.sleep(100);
    return 1;//返回1
}).then(res1 -> {
    throw new RuntimeException("throw error");//抛出异常
}).then(res2->{
    Thread.sleep(100);
    System.out.println("b:"+res2);
    return 2;
}).pCatch(e->{
    Thread.sleep(100);
    System.out.println("c:");//输出c:
    e.printStackTrace();
    return 3;
}).then(res3->{
    Thread.sleep(100);
    System.out.println("d:"+res3);//输出d:3
    return 4;
});
复制代码

结果

a:0
c:
runtimeException:throw error
d:3
复制代码

从上面结果能够看出,在res1出抛出异常后,拒绝了res2处的执行,被pCatch捕获,pCatch返回3,被包装成终值为三、fulfilled状态的promise,在res3打印d:3。

示例5:Promise.all(IPromise ...promises)
IPromise p1 = new Promise.Builder().promiseHanler(executor -> {
    Thread.sleep(1000);
    return 1;
}).build();
IPromise p2 = new Promise.Builder().promiseHanler(executor -> {
    Thread.sleep(4000);
    return 2;
}).build();
IPromise p3 = new Promise.Builder().promiseHanler(executor -> {
    Thread.sleep(2000);
    return 3;
}).build();
long s = System.currentTimeMillis();
Promise.all(p1,p2,p3).then(resolvedData -> {
    Object[] datas = (Object[])resolvedData;
    for(Object d:datas){
        System.out.println(d);
    }
    return null;
},e->e.printStackTrace());
System.out.println("耗时:"+(System.currentTimeMillis()-s));
复制代码

结果

1
2
3
耗时:4033
复制代码
示例6:线程取消
Map<String,Boolean> p1Flag = new HashMap<>();
p1Flag.put("flag",true);
IPromise p1 = new Promise.Builder().externalInput(p1Flag).promiseHanler(executor -> {
    while (((Map<String,Boolean>)executor.getExternalInput()).get("flag")){
        //do something
        System.out.println("p1 正在执行任务");
    }
    System.out.println("p1任务完成,正常结束");
    return 1;
}).build();
IPromise p2 = new Promise.Builder().promiseHanler(executor -> {
    while (!Thread.currentThread().isInterrupted()){
        System.out.println("执行p2正常逻辑");
    }
    System.err.println("p2线程被取消");
    return 2;
}).build();
IPromise p3 = new Promise.Builder().promiseHanler(executor -> {
    Thread.sleep(10);
    throw new RuntimeException("p3抛出异常");
}).build();
IPromise p4 = new Promise.Builder().finalPromise("4",true).build();
long s = System.currentTimeMillis();
Promise.all(p1,p2,p3,p4).then(resolvedData -> {
    Object[] datas = (Object[])resolvedData;
    for(Object d:datas){
        System.out.println(d);
    }
    return null;
},e->e.printStackTrace());
System.out.println("耗时:"+(System.currentTimeMillis()-s));
p1Flag.put("flag",false);
复制代码

可能的结果以下

p1 正在执行任务
p1 正在执行任务
执行p2正常逻辑
执行p2正常逻辑
p1 正在执行任务 
runtimeException:p3抛出异常
p2线程被取消
p1 正在执行任务
p1 正在执行任务
p1 正在执行任务 
p1任务完成,正常结束
复制代码

从上面结果能够看出,开始p1和p2都在正常执行,当p3抛出异常后,Promise.all方法当即返回p3的异常并打印,同时取消p1和p2的执行,因为p2判断了线程状态Thread.currentThread().isInterrupted(),因此p2执行了正常的退出逻辑。p1仍然在执行,并无被取消掉,最后打印p1任务完成,正常结束是由于程序末尾执行了p1Flag.put("flag",false);,不然p1会永远循环打印。

示例7:同步方法异步执行
public class ThenTest {
    public Integer then(int a,int b){
        //打印当前执行现场名称
        System.out.println(Thread.currentThread().getName());
        return a+b;
    }
    public static void main(String[] args){
        //打印主线程名称
        System.out.println(Thread.currentThread().getName());
        List arg = new ArrayList<>();
        arg.add(1);
        arg.add(2);
        //将ThenTest实例then方法异步执行
        Promise.resolve(new ThenTest(),arg).then(resolvedData -> {
            System.out.println(resolvedData);
            return resolvedData;
        }).pCatch(e->{
            e.printStackTrace();
            return 1;
        });
    }
}
复制代码

结果

main
promise-thread-0
3
复制代码
相关文章
相关标签/搜索