我正在尝试在java中实现一个简单的promise系统.我是为特殊目的而做的,所以请不要推荐任何图书馆.
当我尝试实现一个带有Function作为参数的thenApply()方法时,我遇到了一个问题,类似于CompletableFuture,因此返回另一个类型的promise.
承诺界面:
@H_404_9@public interface Promise<T> { Promise<T> then(Consumer<T> handler); <U> Promise<U> thenApply(Function<T, U> handler); }
到目前为止我的实施:
@H_404_9@public class PromiseImpl<T> implements Promise<T> { private List<Consumer<T>> resultHandlers = new ArrayList<>(); public PromiseImpl(CompletableFuture<T> future) { future.thenAccept(this::doWork); } @Override public Promise<T> then(Consumer<T> handler) { resultHandlers.add(handler); return this; } @Override public <U> Promise<U> thenApply(Function<T, U> handler) { // How to implement here??? I don't have the result yet handler.apply(?); } private void onResult(T result) { for (Consumer<T> handler : resultHandlers) { handler.accept(result); } } private Object doWork(T result) { onResult(result); return null; } }
问题是我在thenApply()方法中不知道我最初的未来结果,所以我无法调用我的处理程序.另外,我不想调用future.get(),因为此方法是阻塞的.
我怎么能做这个工作?
解决方法:
真正的问题在于你的Promise类型的设计.它持有一组回调,所有这些回调都将在完成时调用.这是一个基本问题(限制thenApply函数返回类型的通用功能).这可以通过更改Promise实现来解决,每当注册一个处理程序时返回一个新的promise,而不是返回它,这样每个promise对象都有自己的调用处理程序.
除了解决这个问题之外,它还是功能样式编程的更好设计,因为您可以使Promise对象不可变.
我会将界面更改为:
@H_404_9@interface Promise<T> { <U> Promise<U> thenApply(Function<T, U> handler); Promise<Void> thenAccept(Consumer<T> consumer); }
然后可以围绕链接的Promise实例引用的未来对象来完成回调的“链接”.所以实现看起来像:
@H_404_9@class PromiseImpl<T> implements Promise<T> { private CompletableFuture<T> future; public PromiseImpl(CompletableFuture<T> future) { this.future = future; } @Override public <U> Promise<U> thenApply(Function<T, U> function) { return new PromiseImpl<>(this.future.thenApply(function)); } @Override public Promise<Void> thenAccept(Consumer<T> consumer) { return new PromiseImpl<>(this.future.thenAccept(consumer)); } private void onResult(T result) { this.future.complete(result); } private Object doWork(T result) { onResult(result); return null; } }
使用它可以很简单:
@H_404_9@Promise<String> stringPromise = new PromiseImpl<>(new CompletableFuture<String>()); Promise<Long> longPromise = stringPromise.thenApply(str -> Long.valueOf(str.length())); Promise<Void> voidPromise = stringPromise.thenAccept(str -> System.out.println(str));
编辑:
关于检索值的Michael’s comment:未添加的值,因为它不在原始的Promise API中.但它很容易添加:
@H_404_9@T get(); //To the interface
并实施:
@H_404_9@public T get() { //try-catch return this.future.get(); }
注意:这开始看起来越来越像CompletableFuture的重复,这引发了为什么要这样做的问题.但假设此接口中将有其他类似Promise的方法,该方法将包装未来的API.
如果需要使用带有回调列表的相同Promise对象,那么除了使用Function具体类型参数参数化Promise接口之外别无选择:
@H_404_9@public interface Promise<T, U>
并且U将无法成为then或thenApply上的方法泛型参数.
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 [email protected] 举报,一经查实,本站将立刻删除。