2016-03-18 9 views
2

私は各要素が一つのフレームを生成するための情報やリソースを持っているList<Callable<Long>> tasksを生成し、メインスレッドを持っている...問題はアニメーションであり、フラクタルフラクタルアニメーションを生成するためのなぜfuture isDone()がFuture get()のようなプログラムをブロックするのか?

を、プログラムを書いています。私は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()のようなプログラムをブロックし、なぜ私は本当に理解していません!

これは私の最初の質問です。だから、これは大丈夫です。

+1

はそれをしない:

プログラム

は忙しいように見えるので、私はこの解決策を見つけた:Animationクラスになるものの

if (task != null) { task.myCancel(); task.cancel(); } 

:私はこのコードを使用するためのすべてのジョブをキャンセル本当に*ブロックしています(スレッドが 'BLOCKED'状態になっています)か、ビジー状態であるためその行で停止しているようですか? –

+1

ちなみに、CompletionServiceは、スレッドが完了したときに通知される簡単な方法です。 –

+1

もう1つのBTW:あなたのコードに散らばっている 'System.currentTimeMillis() - startTime;を返すのではなく、' call(){long startTime = ...; callInternal();戻り値System.currentTimeMillis() - startTime; } '。また、 'executor.shutDown()'を単一の 'finally'ブロックに入れることを検討してください。 –

答えて

1

私が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(); 
} 
0

ありがとう! *

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(); 
    }); 
} 
[...] 
} 
関連する問題