3

ながら私は除いて(とほぼ同等の種類を考えても、私は、JDK 8 CompletableFutureCompletableFutureとListenableFutureのコルーチン作成者に違いがあるのはなぜですか? Kotlinのコルーチンのソースを調べる

public fun <T> future(
    context: CoroutineContext = DefaultDispatcher, 
    start: CoroutineStart = CoroutineStart.DEFAULT, 
    block: suspend CoroutineScope.() -> T 
): CompletableFuture<T> { 
    require(!start.isLazy) { "$start start is not supported" } 
    val newContext = newCoroutineContext(context) 
    val job = Job(newContext[Job]) 
    val future = CompletableFutureCoroutine<T>(newContext + job) 
    job.cancelFutureOnCompletion(future) 
    ** future.whenComplete { _, exception -> job.cancel(exception) } ** 
    start(block, receiver=future, completion=future) // use the specified start strategy 
    return future 
} 


private class CompletableFutureCoroutine<T>(
    override val context: CoroutineContext 
) : CompletableFuture<T>(), Continuation<T>, CoroutineScope { 
    override val coroutineContext: CoroutineContext get() = context 
    override val isActive: Boolean get() = context[Job]!!.isActive 
    override fun resume(value: T) { complete(value) } 
    override fun resumeWithException(exception: Throwable) { completeExceptionally(exception) } 
    ** doesn't override cancel which corresponds to interrupt task ** 
} 

Guava ListenableFuture

public fun <T> future(
    context: CoroutineContext = DefaultDispatcher, 
    start: CoroutineStart = CoroutineStart.DEFAULT, 
    block: suspend CoroutineScope.() -> T 
): ListenableFuture<T> { 
    require(!start.isLazy) { "$start start is not supported" } 
    val newContext = newCoroutineContext(context) 
    val job = Job(newContext[Job]) 
    val future = ListenableFutureCoroutine<T>(newContext + job) 
    job.cancelFutureOnCompletion(future) 
    start(block, receiver=future, completion=future) // use the specified start strategy 
    return future 
} 

private class ListenableFutureCoroutine<T>(
    override val context: CoroutineContext 
) : AbstractFuture<T>(), Continuation<T>, CoroutineScope { 
    override val coroutineContext: CoroutineContext get() = context 
    override val isActive: Boolean get() = context[Job]!!.isActive 
    override fun resume(value: T) { set(value) } 
    override fun resumeWithException(exception: Throwable) { setException(exception) } 
    ** override fun interruptTask() { context[Job]!!.cancel() } ** 
} 

統合の間(**印)の違いに気づきましたコースListenableFutureを直接完了することはできませんが、なぜこの問題が発生するのかわかりません)。この違いの背景には具体的な理由がありますか?

答えて

5

CompletableFuture.cancelはオープ​​ン(オーバーライド)メソッドですが、のオーバーライド用に設計されたではありません。そのドキュメントではキャンセルの呼び出しを保証していないので、CompletableFutureがキャンセルされたことを知るための唯一の将来的な証明(馬鹿を意図した)方法は、whenCompleteリスナーをインストールすることです。

たとえば、将来のバージョンのJDKでは、内部的にcancelが呼び出されない未来をキャンセルするもう1つの方法を追加することは完全に正当です。このような変更は、CompletableFuture契約のいかなる部分にも違反しません。

これをAbstractFuture.interruptTaskのドキュメントと比較してください。このメソッドは、オーバーライドのために明示的に設計されており、そのドキュメンテーションは、それが呼び出される条件を保証します。したがって、取り消しリスナーをインストールするためのラムダの作成を避けるために、ListenableFutureビルダーの場合、少し効率的な実装を提供できます。

関連する問題