2012-01-20 5 views
3

ExecutorServiceを使ってCallableオブジェクトを実行しました。Callableから中間結果を返すにはどうすればよいですか?

この呼び出し可能コードから中間結果を返すにはどうすればよいですか?

スイングにはjavax.swing.SwingWorker#publish(results)がありますが、私はスイングを使用しません。

+4

ここに同様の質問:あなたはそれが価値

このような何かをチェックあなたがインクリメントそのクラス内(executorが提出される1)、それは価値だと呼び出し元のスレッドからhttp://stackoverflow.com/questions/2275816/ability-to-get-the-progress-on-a-futuret-object and here: http://stackoverflow.com/questions/6346927/java-callable- futuretask-excecuter-how-to-listen-to-finishedタスク – Jim

+0

この質問を+1してみると、私はそれが頼りになると思う。同様のものを探しています。java並行性APIはタスクをまだ完了していないか、完了していないものとしてのみ考慮します。タスクが完了するまで、未来の.get()ブロック。必要なものIMHOは、タスクが多くの状態(ダウンロード、ダウンロード、永続化、完了など)を持つことができるソリューションであり、その状態でタスクを問い合わせることができるAPIです。 – diarmuid

答えて

0

あなたが探しているのはjava.util.concurrent.Futureです。

未来は非同期計算の結果を表します。計算が完了したかどうかを確認し、その完了を待って、計算の結果を取得するためのメソッド が提供されています。結果 は、計算が になったときにメソッドgetを使用して取得することができ、必要に応じて準備ができるまでブロックします。キャンセル方法は です。 にタスクが正常に完了したか、またはキャンセルされたかを判断する追加の方法が提供されています。 の計算が完了すると、計算をキャンセルすることはできません。 がキャンセル可能にするために未来を使用したいが、 が使用できない場合は、Future の形式の型を宣言し、基礎となるタスクの結果としてnullを返すことができます。

+1

未来は最終結果を返しますが、中間結果は返しません。 –

+0

本当ですか! 「中間結果」というものはありません。今まで計算されたものが有用な「中間結果」である点を定義できるような計算であれば、呼び出し元からの中間データにアクセスするために関数とメソッドを編成する必要があります。 – Ingo

1

"中間結果"が実際何であるかは不明です。並行性パッケージで使用されるインタフェースは、単にこれを定義するのではなく、多かれ少なかれ純粋な関数に似ているメソッドを想定しています。したがって

、代わりにこの:

interim = compute something 
final1 = new Pair(interim, fork(new Future() { compute something else })) 

(アイデアではなく、コンパイル可能コードを伝えるために考え擬似コード、)


EDITザ・:

interim  = compute something 
finalresult = compute something else 

はこのような何かをアイデアは:単一のモノリシックなブロックの計算を実行するのではなく、 nterim results "が利用可能な場合)、最初のタスクが前の"中間 "結果を返し、同時に、最終結果を計算する2番目のタスクをフォークするように分割します。もちろん、最終的な結果が得られるように、このタスクのハンドルを呼び出し元に渡す必要があります。通常、これはFutureインタフェースで行われます。

+0

私はあなたのことを理解しました:n個の中間結果を取得し、n個の呼び出しを提出してn個のスレッドを作成し、 'Future#get()'を使って結果をretieveする。 –

+0

私は私の答えを編集します。 – Ingo

0

中間結果をプッシュとして公開する場合は、Observer/Observerableなどの独自のAPIをロールバックする必要があります。もっと簡単なことは、の現在の状態を何らかの自己定義メソッドでポーリングすることです。

2

これにはいくつかの方法があります。あなたはコールバックでそれを行うことができますか、またはキューでそれを行うことができます。

ここでは、コールバックでそれをやっての例です:

public static interface Callback<T> { 
    public void on(T event); 
} 

次に、あなたの進行状況イベント内で何かをするコールバックの実装:

final Callback<String> callback = new Callback<String>() { 
    public void on(String event) { 
     System.out.println(event); 
    } 
}; 

今、あなたは、コールバックを使用することができますあなたのプールで:

Future<String> submit = pool.submit(new Callable<String>() { 
    public String call() throws Exception { 
     for(int i = 0; i < 10; i++) { 
      callback.on("process " + i); 
     } 
     return "done"; 
    } 
}); 
1

あなたのクラスにAtomicIntegerを渡すことができます

public class LongComputation { 

private AtomicInteger progress = new AtomicInteger(0); 

public static void main(String[] args) throws InterruptedException, 
     ExecutionException { 

    AtomicInteger progress = new AtomicInteger(0); 
    LongComputation computation = new LongComputation(progress); 

    ExecutorService executor = Executors.newFixedThreadPool(2); 
    Future<Integer> result = executor.submit(() -> computation.compute()); 
    executor.shutdown(); 

    while (!result.isDone()) { 
     System.out.printf("Progress...%d%%%n", progress.intValue()); 
     TimeUnit.MILLISECONDS.sleep(100); 
    } 

    System.out.printf("Result=%d%n", result.get()); 
} 

public LongComputation(AtomicInteger progress) { 
    this.progress = progress; 
} 

public int compute() throws InterruptedException { 

    for (int i = 0; i < 100; i++) { 
     TimeUnit.MILLISECONDS.sleep(100); 
     progress.incrementAndGet(); 
    } 

    return 1_000_000; 
} 

}

関連する問題