2016-07-27 10 views
1

複数のスレッドから送信されたタスクを実行するために使用される1つのスレッドを持つスレッドプールがあります。このタスクは実際には2つの部分から構成されます。つまり、意味のある結果を持つとかなり時間がかかりますが意味のある結果は返さないcleanupです。現時点(明らかに間違っている)の実装は、このように見えます。以前のcleanupタスクの後にのみ別のperformタスクが実行されるようにするエレガントな方法はありますか?あなたがjava8を使用している場合2つのタスクを連続して実行する

public class Main { 
    private static class Worker { 
     int perform() { 
      return 1; 
     } 

     void cleanup() { 
     } 
    } 

    private static void perform() throws InterruptedException, ExecutionException { 
     ExecutorService pool = Executors.newFixedThreadPool(1); 
     Worker w = new Worker(); 
     Future f = pool.submit(() -> w.perform()); 
     pool.submit(w::cleanup); 
     int x = (int) f.get(); 
     System.out.println(x); 
    } 
} 
+0

正しい方法で提出する必要はありませんか?たとえば、実行、クリーンアップ、実行、クリーンアップ。 –

+0

なぜ 'pool.submit() - > {w.cleanup(); return w.perform();});' –

+0

@СӏаџԁеМаятіиそれは 'perform()'を不必要に遅らせるかもしれません。クリーンアップ()には1分かかり、perform()には1秒かかり、2分ごとにタスクを提出するとします。 – biziclop

答えて

1

でこれを行うことができ、別のタスクが唯一の前のクリーンアップタスクの後に実行される実行することを確保するためのエレガントな方法はありますか?行うには

最も明らかなことは、perform()からcleanup()を呼び出すことですが、私はあなたがそれをやっていない理由があると仮定します。

解決策は現在「間違っている」と言います。どうして?競争条件のために?

synchronized (pool) { 
    Future f = pool.submit(() -> w.perform()); 
    pool.submit(w::cleanup); 
} 

cleanup()perform()直後に来ることを確実にするでしょう:次に、あなたは​​ブロックを追加することができます。​​でパフォーマンスが低下することが心配な場合は、しないでください。

もう1つの解決方法は、ExecutorCompletionService classを使用することですが、1つのスレッドでどのように役立つかわかりません。私は以前に、別のスレッドプールでクリーンアップタスクを実行していたときに使用しました。

1

、あなたはCompletableFuture

CompletableFuture.supplyAsync(() -> w.perform(), pool) 
    .thenApplyAsync(() -> w.cleanup(), pool) 
    .join(); 
+0

この場合、実行とクリーンアップの間にタスクが実行されないことは確かですか? – synapse

関連する問題