簡體   English   中英

多線程環境中的java回調函數

[英]java callback functions in a multi threaded environment

在AJAX中,假設我異步提交請求。 當reposne返回時,它會執行回調函數。

在java多線程環境中實現相同的最佳方法是什么? 即主線程創建子線程並提交任務,然后子線程返回需要由主線程執行的回調函數。

這可能嗎? 在主線程中,我可以執行wait(),在子線程中我可以執行notify(),但在這種情況下,主線程將等到子線程完成。 但是在AJAX中,主線程繼續運行......這就是我想要的

您可以使用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;
      }
    });
  }
}

在上面的示例中,主線程將阻塞,直到第一次計算完成,然后打印它。 然后阻止,直到第二次計算完成,然后打印,等等。

如果您希望在結果可用時(以未指定的順序)打印結果,那么您可以使用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...");
  }
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM