为什么Future isDone()阻止程序像Future get()?

时间:2016-03-18 21:56:10

标签: java multithreading javafx-8 java.util.concurrent

我正在编写一个用于生成分形和分形动画的程序,问题出在动画上......

我有一个生成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()

这是我的第一个问题,所以我希望一切都好。

2 个答案:

答案 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();
    });
}
[...]
}
相关问题