2016-03-18 14 views
2

, sorun Neden Future isDone() Future get() gibi programı engeller? Ben fraktal ve fraktal animasyon üretmek için bir program yazıyorum

Ben her eleman bir kare oluşturmak için bilgi ve kaynaklara sahip bir List<Callable<Long>> tasks üretmek ana iş parçacığı var ... animasyon üzerindedir; sonra iş göndermek için bir ExecutorService kullanın.

Kullanıcı, hesaplamayı durdurmak istiyorsa, bu ikincil parçacığı iptal etme imkânsızlığı problemidir. İşte kod:

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() gibi program blok Gerçekten neden anlaşılmış yok!

Bu benim ilk sorum, umarım her şey yolundadır.

+1

bunu mu:

programı

sadece meşgul görünüyor, bu yüzden bu çözüm bulduk: Animation sınıf haline ederken

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

: ben bu kodu kullanmak için tüm işleri iptal gerçekten * bloğu (iş parçacığı 'BLOCKED' durumunda olduğu gibi), ya da meşgul beklediği için bu satırda durmuş gibi görünüyor mu? –

+1

Bu arada, bir iş parçacığı tamamlandığında bir "Tamamlama Hizmeti" bildiriminin daha kolay bir yolu olabilir. –

+1

Başka bir BTW: 'System.currentTimeMillis() - startTime 'i döndürmek yerine, kodunuzla dağınık olarak, mantığın çoğunu' call() {long startTime =' den çağrılan vo void callInternal() 'içine bölebilirsiniz. ...; callInternal(); System.currentTimeMillis() - startTime döndürün; } '. Ayrıca, executor.shutDown() işlevini tek bir 'finally' bloğuna yerleştirmeyi düşünün. –

cevap

1

Bunu, kullanarak uyguladıysanız, Future s'yi tamamladıkları sırayla döndürmeniz daha kolay olabileceğini düşünüyorum. Örneğin

:

kez
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

Teşekkür ve bana vermeye var yardım et! *

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(); 
    }); 
} 
[...] 
} 
İlgili konular