2009-07-24 10 views
6

JavaのFuturesとScheduledExecutorServiceを調べ始めたところで、私が指定したスケジュールでCallableが実行されていないのはなぜかと思います。このサンプルコードでは、呼び出し可能コードは1回実行されますが、アプリケーションが完了しないか、タスクが再度実行されることはありません(これは私の予想に問題があると確信しています)。Java SchedulerExecutorServiceとFutureTaskのClarityを求めて

ランナブルは問題なく動作します。 Callablesは永遠にブロックされているようですが、なぜ私は分かりません....何が欠けていますか?

ありがとうございます!

public class ExecutorExample { 

    /** 
    * @param args 
    * @throws ExecutionException 
    * @throws InterruptedException 
    */ 
    public static void main(String[] args) throws InterruptedException, ExecutionException { 

     ScheduledExecutorService scheduler = Executors.newScheduledThreadPool(5); 

     FutureTask<ArrayList<String>> ft1 = new FutureTask<ArrayList<String>>(new Callable<ArrayList<String>>(){ 
      @Override 
      public ArrayList<String> call() { 
       ArrayList<String> stuff = new ArrayList<String>(); 
       for(int i = 0;i<10;i++){ 
        String thing ="Adding " + i + " to result"; 
        stuff.add(thing); 
        System.out.println(thing); 

       } 
       return stuff; 
      }}); 

     scheduler.scheduleAtFixedRate(ft1, 0, 1, TimeUnit.SECONDS); 

     System.out.println(ft1.get()); 
     System.out.println(ft1.isDone()); 

    } 
} 

答えて

8

問題はFutureTaskが使用され、そのクラスのドキュメントが言うように、ということである「計算が完了すると、計算が再開またはキャンセルすることはできません。」

のメソッドが一度呼び出された後、次の呼び出しは、タスクのCallableインスタンスに委任されることなく、すぐに戻ります。

唯一のRunnableは、定期的なタスクとして使用することができ、結果を返すことはできません。その代わりにRunnableタスクにrunメソッドの終了時に呼び出すことができるコールバックを与え、タスクの各実行の結果を他のスレッドのリスナーに報告します。

+1

私はこれに従うか分からない。 FutureTaskはRunnableを実装しています。私はそれがcall()メソッドを呼び出し、その結果を格納することを期待しています。私は、ジョブが完了するまでget()をブロックするか、またはキャッシュされた結果をすぐに返します。スケジューラはFutureTaskを実行しないので、call()の結果となり、結果は後で収集するためにキャッシュされますか? –

+1

はい、一度だけです。最初のスケジュールされた呼び出しは、FutureTaskで 'run'を呼び出しますが、Callableで' call'を呼び出さずに 'short-circuits 'メソッドを実行します。しかし、スケジューラーはこれを認識せず、FutureTaskを呼び出すために実行を継続するので、プログラムは終了しません。 – erickson

+0

完璧な意味合いがあります。私はExecutorsとそのilkのためにjavadocsで頭を下げていたので、FutureTaskでその明確な行を完全に見逃してしまった。 私の仕事の結果として起こりたいことは、BlockingQueueが更新された場合、そのキューを各実行可能ファイルに渡すこと、または外部にあるリスナーを実装することです。結果に基づいてキューを操作するrunnable?再度ありがとう –

関連する問題