私は返すシングルスレッドのExecutorの記述しようとしていますCompletableFuture
タスクがスケジュールに基づいてタスクを実行しますときにPriorityBlockingQueue
。
私のタスクは、次のようになります。
public interface DriverTask<V> {
V call(WebDriver driver) throws Throwable;
default TaskPriority getPriority() {
return TaskPriority.LOW;
}
}
public enum TaskPriority {
HIGH,
MEDIUM,
LOW
}
今、私の問題は、私が使用している場合であるCompletableFuture.supplyAsync
メソッドを執行のみを取得Runnable
し、私は私のエグゼキュータは、元のタスクの優先順位を知って取得する方法を知りません。
作成するための別の方法があるCompletableFuture
私は、優先度に基づいてそれらを実行もらうようにしますか?
以下のような方法の原理はsupplyAsync
、新規作成することでCompletableFuture
設定インスタンスとは最終的に、非同期の仕事complete
未来を。
あなたは、あなたの非自明なセットアップのために同じ操作を行うことができます。
private static WebDriver currentDriver() {
…
}
private static final ExecutorService BACKEND
= new ThreadPoolExecutor(1, 1, 1, TimeUnit.MINUTES, new PriorityBlockingQueue<>());
public static <V> CompletableFuture<V> runAsync(DriverTask<V> dt) {
CompletableFuture<V> result = new CompletableFuture<>();
class Job implements Runnable, Comparable<Job>,
CompletableFuture.AsynchronousCompletionTask {
public void run() {
try {
if(!result.isDone()) result.complete(dt.call(currentDriver()));
}
catch(Throwable t) { result.completeExceptionally(t); }
}
private TaskPriority priority() { return dt.getPriority(); }
public int compareTo(Job o) { return priority().compareTo(o.priority()); }
}
BACKEND.execute(new Job());
return result;
}
実装することに注意してくださいCompletableFuture.AsynchronousCompletionTask
必要はありません。それは、これらのマーキングのためだけの大会だRunnable
その目的は完成させることです実装をCompletableFuture
。
ロジックを自分で実装するのもう一つの利点は、この第一段階はで例外をラップする必要がないということですCompletionException
。だから、ときに、呼び出し元のチェーンはexceptionally
、それが元、開封された例外が表示されます。また、呼び出し側のはjoin
なるだろうCompletionException
のコードの位置反映join
はるかに有用な情報を運ぶ、原因として元の例外とコールを。
目的のif(!result.isDone())
実際の完了前に試みがあればそれをスキップすることでCompletableFuture
キャンセル(または完了)されたキュー内で待機している間。完了の試みが開始された後、キャンセルすると、それを中断しません。これは、一般的な動作ですCompletableFuture
。