In meinem Code muss ich eine Aufgabe ausführen, die Rekursions- und parallele Stream-Verarbeitung nutzt, um tief in einen Baum möglicher Spielzüge einzutauchen und zu entscheiden, was der beste Zug ist. Dies erfordert viel Zeit. Um zu verhindern, dass der Benutzer zu lange auf den Computer wartet, um zu "denken", möchte ich eine Zeit von sagen wir 1000 Millisekunden einstellen. Wenn die beste Bewegung nicht innerhalb von 1000 ms gefunden wird, spielt der Computer eine zufällige Bewegung. Mein Problem ist, dass, obwohl ich Abbrechen auf Future (mit möglicherweise auf True gesetzt), die Aufgabe nicht unterbrochen wird und die beschäftigten Threads im Hintergrund ausgeführt werden. Ich habe versucht, in regelmäßigen Abständen nach isInterrupted() auf dem aktuellen zu überprüfen und dann versuchen, auszusteigen, aber das hat nicht geholfen. Irgendwelche Ideen?Wie kann ich die Zukunft einer Multithread-Task abbrechen?
Unten ist mein Code:
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: ich auch ohne versucht, "parallel()" aber auch hier gibt es noch einen einzigen Faden links.
Vielen Dank im Voraus.
https://techblog.bozho.net/unterbrechend-executor-tasks/ – MarianP