net.lulihu.promise.Promise Maven / Gradle / Ivy
package net.lulihu.promise;
import net.lulihu.ObjectKit.StrKit;
import java.util.*;
import java.util.concurrent.*;
import java.util.function.Consumer;
import java.util.function.Function;
/**
* 誓言
*
* @param
*/
public class Promise implements Future {
/**
* 事件
*
* @param 入参
*/
public interface Action {
void invoke(T result);
}
// 任务锁
private final CountDownLatch taskLock = new CountDownLatch(1);
// 绑定回调
private List>> callbacks = new ArrayList<>();
// 返回参数
private V result = null;
// 异常
protected Throwable exception = null;
// 是否已经执行完成
private boolean invoked = false;
public boolean cancel(boolean mayInterruptIfRunning) {
return false;
}
public boolean isCancelled() {
return false;
}
public boolean isDone() {
return invoked;
}
/**
* 获取结果
*
* 该方法立即返回,如果还未产生结果至则返回null
*
* @return 返回处理结果或者null
*/
public V getOrNull() {
return result;
}
/**
* 获取处理结果
*
* 该方法会阻塞直到产生结果值或者被中断抛出例外
*
* @return 返回处理结果
* @throws InterruptedException 在处理过程中被中断抛出
* @throws ExecutionException 执行过程中出现例外抛出
*/
public V get() throws InterruptedException, ExecutionException {
taskLock.await();
if (exception != null) {
// 结果是一个例外 - 抛出它
throw new ExecutionException(exception);
}
return result;
}
/**
* 在指定时间内获取处理结果
*
* 该方法会阻塞指定长度的时间,如果在指定时间内返回处理结果则返回,如果没有返回结果则抛出超时例外
*
* @param timeout 时间
* @param unit 单位
* @return 处理结果
* @throws InterruptedException 在处理过程中被中断抛出
* @throws ExecutionException 执行过程中出现例外抛出
* @throws TimeoutException 指定时间内未能返回处理结果则抛出
*/
public V get(long timeout, TimeUnit unit) throws InterruptedException, ExecutionException, TimeoutException {
if (!taskLock.await(timeout, unit)) {
throw new TimeoutException(StrKit.format("承诺在 {} {} 未能做到", timeout, unit));
}
if (exception != null) {
// 结果是一个例外 - 抛出它
throw new ExecutionException(exception);
}
return result;
}
/**
* 结果
*
* @param result 结果
*/
void invoke(V result) {
invokeWithResultOrException(result, null);
}
/**
* 例外
*
* @param t 例外
*/
void invokeWithException(Throwable t) {
invokeWithResultOrException(null, t);
}
private void invokeWithResultOrException(V result, Throwable t) {
synchronized (this) {
if (invoked) return;
invoked = true;
this.result = result;
this.exception = t;
taskLock.countDown();
}
// 执行结束 执行回调
for (Action> callback : callbacks) {
callback.invoke(this);
}
}
/**
* 增加承诺
*
* 如果当前承诺正在实现过程中则直接执行否则添加到回调
*
* @param callback 回调
*/
public void onRedeem(Action> callback) {
synchronized (this) {
if (!invoked) {
callbacks.add(callback);
}
}
if (invoked) {
callback.invoke(this);
}
}
/**
* 等待所有承诺完成 再返回
*
* @param promises 承诺s
* @param 泛型
* @return {@linkplain Promise}
*/
public static Promise> waitAll(final Promise... promises) {
return waitAll(Arrays.asList(promises));
}
/**
* 等待所有承诺完成 在返回
*
* @param promises 承诺s
* @param 泛型
* @return {@linkplain Promise}
*/
public static Promise> waitAll(final Collection> promises) {
final CountDownLatch waitAllLock = new CountDownLatch(promises.size());
final Promise> result = new Promise>() {
@Override
public boolean cancel(boolean mayInterruptIfRunning) {
boolean r = true;
for (Promise f : promises) {
r = r & f.cancel(mayInterruptIfRunning);
}
return r;
}
@Override
public boolean isCancelled() {
boolean r = true;
for (Promise f : promises) {
r = r & f.isCancelled();
}
return r;
}
@Override
public boolean isDone() {
boolean r = true;
for (Promise f : promises) {
r = r & f.isDone();
}
return r;
}
@Override
public List get() throws InterruptedException, ExecutionException {
waitAllLock.await();
List r = new ArrayList<>();
for (Promise f : promises) {
r.add(f.get());
}
return r;
}
@Override
public List get(long timeout, TimeUnit unit) throws InterruptedException, ExecutionException, TimeoutException {
if (!waitAllLock.await(timeout, unit)) {
throw new TimeoutException(String.format("Promises didn't redeem in %s %s", timeout, unit));
}
return get();
}
};
final Action> action = completed -> {
waitAllLock.countDown();
if (waitAllLock.getCount() == 0) {
try {
result.invoke(result.get());
} catch (Exception e) {
result.invokeWithException(e);
}
}
};
if (promises.isEmpty()) {
result.invoke(Collections.emptyList());
} else {
for (Promise f : promises) {
f.onRedeem(action);
}
}
return result;
}
/**
* 使用誓言对象
*
* @param v 参数
* @param 入参类型
* @return 返回一个包装入参的誓言对象
*/
public static Promise pure(final V v) {
Promise p = new Promise<>();
p.invoke(v);
return p;
}
/**
* 使用誓言对象
*
* @param t 异常
* @param v
* @return 返回一个包装指定异常的誓言对象
*/
public static Promise wrap(final Throwable t) {
Promise p = new Promise<>();
p.invokeWithException(t);
return p;
}
/**
* 在原有的誓言流程上继续绑定誓言
*
* @param function 誓言转换函数
* @param 绑定誓言的类型
* @return 绑定后的誓言对象
*/
public Promise bind(final Function> function) {
Promise result = new Promise<>();
this.onRedeem(callback -> {
try {
V v = callback.get();
Promise applicationResult = function.apply(v);
applicationResult.onRedeem(applicationCallback -> {
try {
R r = applicationCallback.get();
result.invoke(r);
} catch (Throwable e) {
result.invokeWithException(e);
}
});
} catch (Throwable e) {
result.invokeWithException(e);
}
});
return result;
}
/**
* 使用方式
*
* Promise apply = Promise.fmap((Function) i -> i + "-").apply(Promise.pure(10));
*
* @param function 处理表达式
* @param 入参
* @param 出参
* @return {@linkplain Function}
*/
public static Function, Promise> fmap(Function function) {
return p -> {
Promise result = new Promise<>();
p.onRedeem(callback -> {
try {
T t = callback.get();
R r = function.apply(t);
result.invoke(r);
} catch (Throwable e) {
result.invokeWithException(e);
}
});
return result;
};
}
/**
* 加入多个方式
*
* @param promise 誓言
* @param 入参类型
* @return {@linkplain Promise}
*/
public static Promise join(Promise> promise) {
Promise result = new Promise<>();
promise.onRedeem(callback -> {
try {
Promise inner = callback.get();
inner.onRedeem(innerCallback -> {
try {
T t = innerCallback.get();
result.invoke(t);
} catch (InterruptedException | ExecutionException e) {
result.invokeWithException(e);
}
});
} catch (InterruptedException | ExecutionException e) {
result.invokeWithException(e);
}
});
return result;
}
/**
* 使用方式
*
* Promise promise = Promise.lift((Function) i -> i++).apply(10);
*
* @param function 表达式
* @param 入参类型
* @param 返回参数
* @return {@linkplain Function}
*/
public static Function> lift(Function function) {
return function.andThen(Promise::pure);
}
/**
* 使用方式
*
* Promise.lift((Consumer