我注意到,如果将来调用cancel
,则thenApply
方法的覆盖无效。派生的未来不知道原始文档具有此类替代。下面的代码演示了该问题。
有什么方法可以正确地重写此方法而又不会失去改变未来的可能性?
import java.util.concurrent.CompletableFuture;
public class Main {
public static void main(String[] args){
CompletableFuture<Object> unmodified = new CompletableFuture<>(){
@Override
public boolean cancel(boolean mayInterruptIfRunning) {
System.out.println("----> cancelling unmodified");
return super.cancel(mayInterruptIfRunning);
}
};
unmodified
.cancel(true);
CompletableFuture<Object> modified = new CompletableFuture<>(){
@Override
public boolean cancel(boolean mayInterruptIfRunning) {
System.out.println("----> cancelling modified");
return super.cancel(mayInterruptIfRunning);
}
};
unmodified
.thenApply(x -> x)
.cancel(true);
System.out.println("----> end");
}
// OUTPUT
// > Task :Main.main()
// ----> cancelling unmodified
// ----> end
}
您需要Java 9或更高版本。然后,所有创建新的依赖未来的方法都将调用工厂方法newIncompleteFuture()
,您可以对其进行覆盖:
public static void main(String arg[]) {
class MyFuture<T> extends CompletableFuture<T> {
@Override
public boolean cancel(boolean mayInterruptIfRunning) {
System.out.println("customized cancel");
return super.cancel(mayInterruptIfRunning);
}
@Override
public <U> CompletableFuture<U> newIncompleteFuture() {
return new MyFuture<>();
}
}
MyFuture<Object> future = new MyFuture<>();
System.out.print("direct: ");
future.cancel(true);
System.out.print("indirect: ");
future.thenApply(x -> x).cancel(true);
System.out.print("even longer chain: ");
future.thenApply(x -> x).exceptionally(t -> null).cancel(true);
System.out.println("end");
}
direct: customized cancel
indirect: customized cancel
even longer chain: customized cancel
end
但是请注意,对于CompletableFuture
,取消与CancellationException
的特殊完成没有区别。因此,有人可以调用completeExceptionally(new CancellationException())
而不是cancel(...)
,以达到相同的效果。
没有直接的方法可以执行所需的操作,因为thenApply
返回一个新的CompletableFuture
对象。但是,如果确实需要执行此操作,则可以尝试覆盖CompletableFuture
类本身。
让我解释一下!CompletableFuture.thenApply()
方法还调用uniApplyStage
类的CompletableFuture
私有方法,其中创建了new CompletableFuture()
实例以返回。 (我反编译了Java源代码以进行检查。)
您不能覆盖此方法,因为它是私有方法。但是,如果您;
CompletableFuture
uniApplyStage
实例时将@Override
方法从cancel
更改为new CompletableFuture<V>()
。从理论上讲,您应该能够完成所有这一切。
但是,问题仍然存在。您多么想完成这项工作? :D
根据我的诚实观点,将此答案视为最后的选择。