1

AJAX で、非同期でリクエストを送信するとします。reposne が を返すと、コールバック関数が実行されます。

Javaマルチスレッド環境で同じものを実装する最良の方法は何ですか? つまり、メイン スレッドが子スレッドを作成し、タスクを送信すると、子スレッドは、メイン スレッドによって実行される必要があるコールバック関数を返します。

これは可能ですか?メインスレッドではwait()を実行でき、子スレッドではnotify()を実行できますが、その場合、メインスレッドは子スレッドが終了するまで待機します。しかし、AJAX では、メイン スレッドは動作を継続します...それが私が望んでいることです

4

1 に答える 1

3

を使用ExecutorServiceしてバックグラウンドでタスクを実行し、返された のメソッドを使用しFutureて結果を待つことができます。例えば:

class Main {
  private static final ExecutorService es = Executors.newCachedThreadPool();

  public static void main(final String... args) throws Throwable {
    List<Future<Integer>> results = new ArrayList<>();
    for (int i = 0; i < 10; i++) {
      results.add(asyncSum(i, i*i));
    }
    // here, in the main thread, you can do whatever you want
    // while the calculations are performed in background threads
    // ...

    // after the main thread finishes what it was doing, it
    // can process the futures
    for (final Future<Integer> result : results) {
      System.out.println(result.get());
    }
  }

  // this method launches a calculation on a worker thread and immediately
  // returns a Future, which is a reference to the result of the calculation
  // once it is completed
  private static Future<Integer> asyncSum(final int a, final int b) {
    return es.submit(new Callable<Integer>() {
      @Override public Integer call() throws Exception {
        return a + b;
      }
    });
  }
}

上記の例では、メイン スレッドは最初の計算が完了するまでブロックし、それを出力します。次に、2 番目の計算が完了するまでブロックし、それを出力します。

結果が利用可能になったときに(不特定の順序で)結果を出力したい場合は、 を使用できます。結果のリストを取得して反復処理する代わりに、メソッドCompletionServiceを介して CompletionService 自体から先物を取得します。.take()、計算が終了するまでブロックするか.poll()、終了した計算がある場合は Future を返し、計算が終了していない場合は null を返します。このようにして、メインスレッドはブロックされません。

次の例では、CompletionService. これは、決してブロックせず、バックグラウンド スレッドを使用して計算を行い、結果が利用可能になったときに処理するメイン スレッドを示しています。

class Main {
  public static void main(String[] args) throws Throwable {
    final ExecutorService es = Executors.newCachedThreadPool();
    final CompletionService<Integer> cs = new ExecutorCompletionService<>(es);

    submitSomeCalculations(cs);

    while (true) {
      doMainThreadWork();
      processFinishedCalculations(cs);
    }
  }

  private static void submitSomeCalculations(final CompletionService<Integer> cs) {
    for (int i = 0; i < 10; i++) {
      submitAsyncSum(cs, i, i * i);
    }
  }

  private static void submitAsyncSum(final CompletionService<Integer> cs, final int a, final int b) {
    cs.submit(new Callable<Integer>() {
      @Override public Integer call() throws Exception {
        Thread.sleep(100 + (long) (Math.random() * 900));
        return a + b;
      }
    });
  }

  private static void processFinishedCalculations(final CompletionService<Integer> cs) throws ExecutionException, InterruptedException {
    while (true) {
      final Future<Integer> result = cs.poll();
      if (result == null) {
        System.out.println("> no finished results...");
        break;
      } else {
        System.out.println("> result available: " + result.get());
      }
    }
  }

  static void doMainThreadWork() {
    System.out.println("work from main thread...");
  }
}
于 2013-07-05T19:51:10.697 に答える