質問

まず最初に、私は API java.util.concurrent についてはまったくの初心者であるため、おそらく私がやっていることは完全に間違っていると言わなければなりません。

私は何をしたいのですか?

基本的に 2 つの別個の処理 (と呼ばれる) を実行する Java アプリケーションがあります。 私の最初のプロセス, mySecondProcess) ですが、これらの処理は同時に実行する必要があります。

それで、私はそれをしようとしました:

public void startMyApplication() {
    ExecutorService executor = Executors.newFixedThreadPool(2);
    FutureTask<Object> futureOne = new FutureTask<Object>(myFirstProcess);
    FutureTask<Object> futureTwo = new FutureTask<Object>(mySecondProcess);
    executor.execute(futureOne);
    executor.execute(futureTwo);
    while (!(futureOne.isDone() && futureTwo.isDone())) {
        try {
            // I wait until both processes are finished.
            Thread.sleep(1000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
    logger.info("Processing finished");
    executor.shutdown();
    // Do some processing on results
    ...
}

私の最初のプロセス そして mySecondProcess を実装するクラスです Callable<Object>, 、すべての処理は call() メソッドで行われます。

非常にうまく機能していますが、それが正しい方法であるかどうかはわかりません。私がやりたいことを実現する良い方法はありますか?そうでない場合は、コードを強化するためのヒントをいくつか教えてください (ただし、コードをできるだけシンプルに保つことができます)。

役に立ちましたか?

解決

あなたはget()メソッドを使用したほうが良いと思います。

futureOne.get();
futureTwo.get();

それは、処理を終えたことをスレッドからの通知を待つどちらも、これはあなたが今、効率的でもエレガントされていない使用しています。

ビジー待機-でタイマー節約します

ボーナスとして、あなたが眠ると応答を待つスレッドの最大時間を定義し、それ以外の場合は実行を継続可能にするAPIのget(long timeout, TimeUnit unit)を持っています。

を参照してください。詳細情報のためのJava API でます。

他のヒント

の用途 FutureTask 上記は許容範囲ですが、決して慣用的ではありません。実際にラッピングしているのは、 余分な FutureTask あなたが提出したものの周りに ExecutorService. 。あなたの FutureTask として扱われます Runnable によって ExecutorService. 。内部的には、 FutureTask-として-Runnable 新しいで FutureTask そしてそれをあなたに返します Future<?>.

代わりに、 Callable<Object> インスタンスを CompletionService. 。2つドロップします Callable経由です submit(Callable<V>), 、それから振り返って電話します CompletionService#take() 2回(提出ごとに1回) Callable)。これらの呼び出しは、送信されたタスクが 1 つ完了し、その後他のタスクが完了するまでブロックされます。

すでに持っていることを考えると、 Executor 手に、新しいものを構築する ExecutorCompletionService その周りにタスクをドロップします。ぐるぐる回って寝て待ってはいけません。 CompletionService#take() タスクのいずれかが完了する (実行が終了するかキャンセルされる) か、スレッドが待機するまでブロックされます。 take() 中断される。

のYuvalのソリューションは、罰金です。別の方法として、あなたもこれを行うことができます:

ExecutorService executor = Executors.newFixedThreadPool();
FutureTask<Object> futureOne = new FutureTask<Object>(myFirstProcess);
FutureTask<Object> futureTwo = new FutureTask<Object>(mySecondProcess);
executor.execute(futureOne);
executor.execute(futureTwo);
executor.shutdown();
try {
  executor.awaitTermination(Long.MAX_VALUE, TimeUnit.NANOSECONDS);
} catch (InterruptedException e) {
  // interrupted
}

このアプローチの利点は何ですか?違いの多くは、この方法は、あなたが任意の複数のタスクを受け入れ執行を停止することを除いて、実際にはありません(あなたが行うことができ、他のあまりにも)。でも、私はその一つに、このイディオムを好む傾向にある。

また、もしどちらかあなたが悪いかもしれない両方のタスクが実行されていると仮定し、あなたのコードの一部、で終わる可能性が例外をスロー)(入手ます。

あなたがinvokeall使用することができます(コレクション....)メソッド

package concurrent.threadPool;

import java.util.Arrays;
import java.util.List;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;

public class InvokeAll {

    public static void main(String[] args) throws Exception {
        ExecutorService service = Executors.newFixedThreadPool(5);
        List<Future<java.lang.String>> futureList = service.invokeAll(Arrays.asList(new Task1<String>(),new Task2<String>()));

        System.out.println(futureList.get(1).get());
        System.out.println(futureList.get(0).get());
    }

    private static class Task1<String> implements Callable<String>{

        @Override
        public String call() throws Exception {
            Thread.sleep(1000 * 10);
            return (String) "1000 * 5";
        }

    }

    private static class Task2<String> implements Callable<String>{

        @Override
        public String call() throws Exception {
            Thread.sleep(1000 * 2);
            int i=3;
            if(i==3)
                throw new RuntimeException("Its Wrong");
            return (String) "1000 * 2";
        }

    }
}

あなたのfutureTasksは2、より多くの場合は、[ListenableFuture][1]をご検討くださいます。

  

いくつかの操作は、別の操作次第、開始しなければならない場合には   開始 - 「のファンアウトの」 - ListenableFutureだけで動作します。それはすべてをトリガー   要求されたコールバック。少しより多くの仕事では、我々はできる「のファンインを、」か   すぐに他のいくつかのように計算を取得するListenableFutureをトリガ   先物はすべて終了しました。

scroll top