我正在编写一个用于生成分形和分形动画的程序,问题出在动画上......
我有一个生成List<Callable<Long>> tasks
的主线程,其中每个元素都有生成一帧的信息和资源;然后我使用ExecutorService
提交作品。
问题在于,如果用户想要停止微积分,则无法取消这些辅助线程。这是代码:
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;
}
}
我真的不明白为什么Future.isDone()
阻止程序如Future.get()
!
这是我的第一个问题,所以我希望一切都好。
答案 0 :(得分:2)
我认为如果您使用CompletionService
实现此功能可能更容易,Future
按照完成的顺序返回Executor executor = Executors.newFixedThreadPool(4);
try {
CompletionService completionService = new ExecutorCompletionService(executor);
List<Future<Long>> futures = new ArrayList<>();
for (Callable<Long> task : task) {
futures.add(completionService.submit(task));
}
int pending = futures.size();
while (pending > 0) {
// Wait for up to 100ms to see if anything has completed.
// The completed future is returned if one is found; otherwise null.
// (Tune 100ms as desired)
Future<Long> completed = completionService.poll(100, TimeUnit.MILLISECONDS);
if (completed != null) {
updateProgress(count.incrementAndGet(), maxCount);
--pending;
}
if (isCancelled()) {
// Cancel all task etc.
break;
}
}
} finally {
executor.shutdown();
}
。
例如:
public List<List<string>> ListItems { get; set; }
var itemList = new List<string>();
itemList.Add("1");
itemList.Add("John Doe");
ListItems.Add(itemList);
itemList = new List<string>();
itemList.Add("2");
itemList.Add("Jane Doe");
ListItems.Add(itemList);
itemList = new List<string>();
itemList.Add("3");
itemList.Add("Sammy Doe");
ListItems.Add(itemList);
答案 1 :(得分:0)
感谢您抽出时间和帮助!
该程序似乎只是忙,所以我找到了这个解决方案:取消所有工作我使用此代码:
if (task != null) {
task.myCancel();
task.cancel();
}
Animation
班成为:
public class Animation extends Task<Long> {
[...]
@Override
protected Long call() throws Exception {
long startTime = System.currentTimeMillis();
ExecutorService executor = null;
try {
frames = new WritableImage[frameNumber];
updateProgress(count.incrementAndGet(), maxCount);
if (isCancelled()) {
return System.currentTimeMillis() - startTime;
}
executor = Executors.newWorkStealingPool();
//executor = Executors.newFixedThreadPool(4);
updateProgress(count.incrementAndGet(), maxCount);
if (isCancelled()) {
return System.currentTimeMillis() - startTime;
}
tasks = initTasks();
updateProgress(count.incrementAndGet(), maxCount);
if (isCancelled()) {
return System.currentTimeMillis() - startTime;
}
result = executor.invokeAll(tasks);
updateProgress(count.incrementAndGet(), maxCount);
makeAnimation();
updateProgress(count.incrementAndGet(), maxCount);
}
catch (InterruptedException ex) {
System.err.println(ex.toString());
}
finally {
if (executor != null) {
executor.shutdown();
}
}
return System.currentTimeMillis() - startTime;
}
[...]
public void myCancel() {
tasks.stream().forEach((t) -> {
((CartesianFractal)t).myCancel();
});
}
[...]
}