Ich bin ein Programm zur Erzeugung von fraktalen und fraktale Animation zu schreiben, ist das Problem auf die Animation ...Warum Zukunft isDone() blockiert das Programm wie Future get()?
ich einen Haupt-Thread haben, die eine List<Callable<Long>> tasks
erzeugen, wobei jedes Element die Informationen und Ressourcen für die Erzeugung eines Rahmens hat; Dann benutze ich eine ExecutorService
, um die Arbeit einzureichen.
Das Problem liegt in der Unmöglichkeit, diese sekundären Thread abzubrechen, wenn der Benutzer den Kalkül stoppen möchte. Hier ist der Code:
public class Animation extends Task<Long> {
protected Long call() throws Exception {
long startTime = System.currentTimeMillis();
WritableImage[] frames = new WritableImage[frameNumber];
List<Callable<Long>> tasks = new ArrayList<>();
updateProgress(count.incrementAndGet(), maxCount);
if (isCancelled()) {
return System.currentTimeMillis() - startTime;;
}
for (int k = 0; k < frameNumber; k++) {
frames[k] = new WritableImage(
(int) start.getCartesianPlane().getWidth(),
(int) start.getCartesianPlane().getHeight());
CartesianFractal tmp = FractalFactory.bulidFractal(
selectedFractal, nextDataBox(k), colorPalette);
tmp.setOnFinish(t -> {
updateProgress(count.incrementAndGet(), maxCount);
return null;
});
tasks.add((Callable<Long>) tmp);
if (isCancelled()) {
return System.currentTimeMillis() - startTime;;
}
}
executor = Executors.newFixedThreadPool(4);
updateProgress(count.incrementAndGet(), maxCount);
if (isCancelled()) {
return System.currentTimeMillis() - startTime;
}
try {
result = executor.invokeAll(tasks);
}
catch (InterruptedException ex) {
System.err.println(ex.toString());
}
// Check if all tasks are finished
boolean finished = false;
while (!finished) {
finished = true;
// Check if it is all done
for (Future<Long> r : result) {
finished = finished && r.isDone(); // THE PROGRAM BLOCKS HERE
// Check if the task was cancelled
if (isCancelled()) {
// Cancell all task
tasks.stream().forEach((t) -> {
((CartesianFractal)t).myCancel();
});
// Turnoff the executor
executor.shutdown();
return System.currentTimeMillis() - startTime;
}
}
}
// Turnoff the executor
executor.shutdown();
updateProgress(count.incrementAndGet(), maxCount);
makeAnimation();
updateProgress(count.incrementAndGet(), maxCount);
return System.currentTimeMillis() - startTime;
}
}
ich nicht wirklich verstanden, warum Future.isDone()
das Programm wie Future.get()
blockieren!
Das ist meine erste Frage, also hoffe ich, dass alles in Ordnung ist.
es funktioniert * wirklich * blocken dort (wie im Thread ist in "BLOCKED" Zustand), oder scheint es nur auf dieser Linie gestoppt werden, weil es beschäftigt ist - warten? –
Übrigens ist ein 'CompletionService' möglicherweise eine einfachere Möglichkeit, benachrichtigt zu werden, wenn ein Thread fertig ist. –
Ein anderer BTW: anstatt 'system.currentTimeMillis() - startTime; return 'zurückzugeben, können Sie den größten Teil der Logik in' void callInternal() 'aufteilen, die von' call() {long startTime = aufgerufen wird ...; callInternal(); Zurückgeben von System.currentTimeMillis() - startTime; } '. Ziehen Sie auch in Erwägung, 'executor.shutDown()' in einen einzigen 'finally' Block zu setzen. –