私のコードでは、可能なゲームの動きの木に深く入り、何が最良の動きになるかを判断するために、再帰と並列ストリーム処理を頻繁に使用するタスクを実行する必要があります。これには多くの時間がかかりますので、ユーザーがコンピュータが「1000ミリ秒」などの時間を設定したいと思うのを待つのを待たされるのを防ぐためです。最高の動きが1000ミリ秒で見つからない場合、コンピュータはランダムな動きをするでしょう。 私の問題は、私は未来をキャンセルする(trueに設定されている割り込みで)と呼びますが、タスクが中断されず、ビジースレッドがバックグラウンドで実行され続けることです。 私は定期的に現在のisInterrupted()をチェックしてから救済しようとしましたが、これは役に立ちませんでした。 アイデアマルチスレッド・ビジー・タスクの未来を取り消すにはどうしたらいいですか?
public Move bestMove() {
ExecutorService executor = Executors.newSingleThreadExecutor();
Callable<Move> callable =() -> bestEntry(bestMoves()).getKey();
Future<Move> future = executor.submit(callable);
try {
return future.get(1000, TimeUnit.MILLISECONDS);
} catch (InterruptedException e) {
System.exit(0);
} catch (ExecutionException e) {
throw new RuntimeException(e);
} catch (TimeoutException e) {
future.cancel(true);
return randomMove();
}
return null;
}
private Move randomMove() {
Random random = new Random();
List<Move> moves = state.possibleMoves();
return moves.get(random.nextInt(moves.size()));
}
private <K> Map.Entry<K, Double> bestEntry(Map<K, Double> map) {
List<Map.Entry<K, Double>> list = new ArrayList<>(map.entrySet());
Collections.sort(list, (e1, e2) -> (int) (e2.getValue() - e1.getValue()));
return list.get(0);
}
private <K> Map.Entry<K, Double> worstEntry(Map<K, Double> map) {
List<Map.Entry<K, Double>> list = new ArrayList<>(map.entrySet());
Collections.sort(list, (e1, e2) -> (int) (e1.getValue() - e2.getValue()));
return list.get(0);
}
private Map<Move, Double> bestMoves() {
Map<Move, Double> moves = new HashMap<>();
state.possibleMoves().stream().parallel().forEach(move -> {
if (!Thread.currentThread().isInterrupted()) {
Game newState = state.playMove(move);
Double score = newState.isTerminal() ? newState.utility()
: worstEntry(new (newState).worstMoves()).getValue();
moves.put(move, score);
}
});
return moves;
}
private Map<Move, Double> worstMoves() {
Map<Move, Double> moves = new HashMap<>();
state.possibleMoves().stream().parallel().forEach(move -> {
if (!Thread.currentThread().isInterrupted()) {
Game newState = state.playMove(move);
Double score = newState.isTerminal() ? -newState.utility()
: bestEntry(new (newState).bestMoves()).getValue();
moves.put(move, score);
}
});
return moves;
}
PS:
以下は私のコードである私もせずに試してみました「パラレル()」が、再び、単一のスレッドが実行したまま残っています。
ありがとうございます。
https://techblog.bozho.net/interrupting-executor-tasks/ – MarianP