が手軽に行うことができる将来<Future<T>>への将来<T>?
-
24-09-2019 - |
質問
私にはあるコードの依頼に別のスレッドか否かを問わず提出を要求します。る利回りは、戻り値の型 Future<Future<T>>
.あのいくつかの非凶悪なにすぐにこの入 Future<T>
この待機を完成全体の今後のチェーン?
って、グァバの図書館の取扱いその他の並行処理で楽しいものの、代替として、Googleのコレクションやそのものがないのですがる何かを見つけなければならないこと。
解決
グァバの130を追加 Futures.dereference
関係ではないかと思います。を必要とし ListenableFuture<ListenableFuture>
, よるのではなく、平野 Future<Future>
.営業、平野 Future
える必要があるmakeListenable、それぞれが専用スレッドの寿命のタスクとしてはより明確な方法により新しい名前 JdkFutureAdapters.listenInPoolThread
).)
他のヒント
guava ライブラリを使用するもう 1 つの実装は、はるかに単純です。
import java.util.concurrent.*;
import com.google.common.util.concurrent.*;
import com.google.common.base.*;
public class FFutures {
public <T> Future<T> flatten(Future<Future<T>> future) {
return Futures.chain(Futures.makeListenable(future), new Function<Future<T>, ListenableFuture<T>>() {
public ListenableFuture<T> apply(Future<T> f) {
return Futures.makeListenable(f);
}
});
}
}
私は、これは将来の契約を実装するために行うことができるよう最善だと思います。私はそれが契約を満たしていることを確認することができるだけようuncleverようであることのタックを取りました。タイムアウト付きのgetのない、特に実装ます。
import java.util.concurrent.*;
public class Futures {
public <T> Future<T> flatten(Future<Future<T>> future) {
return new FlattenedFuture<T>(future);
}
private static class FlattenedFuture<T> implements Future<T> {
private final Future<Future<T>> future;
public FlattenedFuture(Future<Future<T>> future) {
this.future = future;
}
public boolean cancel(boolean mayInterruptIfRunning) {
if (!future.isDone()) {
return future.cancel(mayInterruptIfRunning);
} else {
while (true) {
try {
return future.get().cancel(mayInterruptIfRunning);
} catch (CancellationException ce) {
return true;
} catch (ExecutionException ee) {
return false;
} catch (InterruptedException ie) {
// pass
}
}
}
}
public T get() throws InterruptedException,
CancellationException,
ExecutionException
{
return future.get().get();
}
public T get(long timeout, TimeUnit unit) throws InterruptedException,
CancellationException,
ExecutionException,
TimeoutException
{
if (future.isDone()) {
return future.get().get(timeout, unit);
} else {
return future.get(timeout, unit).get(0, TimeUnit.SECONDS);
}
}
public boolean isCancelled() {
while (true) {
try {
return future.isCancelled() || future.get().isCancelled();
} catch (CancellationException ce) {
return true;
} catch (ExecutionException ee) {
return false;
} catch (InterruptedException ie) {
// pass
}
}
}
public boolean isDone() {
return future.isDone() && innerIsDone();
}
private boolean innerIsDone() {
while (true) {
try {
return future.get().isDone();
} catch (CancellationException ce) {
return true;
} catch (ExecutionException ee) {
return true;
} catch (InterruptedException ie) {
// pass
}
}
}
}
}
あなたが好きなクラスを作成することができます:
public class UnwrapFuture<T> implements Future<T> {
Future<Future<T>> wrappedFuture;
public UnwrapFuture(Future<Future<T>> wrappedFuture) {
this.wrappedFuture = wrappedFuture;
}
public boolean cancel(boolean mayInterruptIfRunning) {
try {
return wrappedFuture.get().cancel(mayInterruptIfRunning);
} catch (InterruptedException e) {
//todo: do something
} catch (ExecutionException e) {
//todo: do something
}
}
...
}
あなたは、get()を上げることができますが、他の方法がないことができます。
という例外に対処する必要がありますこのはそれで私の最初の刺し傷だったが、私はそれでたくさん間違っているがあることを確認しています。私はちょうどFutures.compress(f)
のようなものに置き換えることをより幸せになると思います。
public class CompressedFuture<T> implements Future<T> {
private final Future<Future<T>> delegate;
public CompressedFuture(Future<Future<T>> delegate) {
this.delegate = delegate;
}
@Override
public boolean cancel(boolean mayInterruptIfRunning) {
if (delegate.isDone()) {
return delegate.cancel(mayInterruptIfRunning);
}
try {
return delegate.get().cancel(mayInterruptIfRunning);
} catch (InterruptedException e) {
throw new RuntimeException("Error fetching a finished future", e);
} catch (ExecutionException e) {
throw new RuntimeException("Error fetching a finished future", e);
}
}
@Override
public T get() throws InterruptedException, ExecutionException {
return delegate.get().get();
}
@Override
public T get(long timeout, TimeUnit unit) throws InterruptedException, ExecutionException, TimeoutException {
long endTime = System.currentTimeMillis() + unit.toMillis(timeout);
Future<T> next = delegate.get(timeout, unit);
return next.get(endTime - System.currentTimeMillis(), TimeUnit.MILLISECONDS);
}
@Override
public boolean isCancelled() {
if (!delegate.isDone()) {
return delegate.isCancelled();
}
try {
return delegate.get().isCancelled();
} catch (InterruptedException e) {
throw new RuntimeException("Error fetching a finished future", e);
} catch (ExecutionException e) {
throw new RuntimeException("Error fetching a finished future", e);
}
}
@Override
public boolean isDone() {
if (!delegate.isDone()) {
return false;
}
try {
return delegate.get().isDone();
} catch (InterruptedException e) {
throw new RuntimeException("Error fetching a finished future", e);
} catch (ExecutionException e) {
throw new RuntimeException("Error fetching a finished future", e);
}
}
}