简体   繁体   English

多线程环境中的java回调函数

[英]java callback functions in a multi threaded environment

In AJAX, suppose i submit a request asynchronously. 在AJAX中,假设我异步提交请求。 When the reposne returns , it executes a callback function. 当reposne返回时,它会执行回调函数。

What is the best way to implement the same in a java multithreaded environment? 在java多线程环境中实现相同的最佳方法是什么? ie Main thread creates a child thread and submits a task and then the child thread returns a callback function needs to be executed by the main thread. 即主线程创建子线程并提交任务,然后子线程返回需要由主线程执行的回调函数。

Is this possible? 这可能吗? In main thread I can do wait() and in child thread i can do notify() but in that case the main thread will wait until the child thread finishes. 在主线程中,我可以执行wait(),在子线程中我可以执行notify(),但在这种情况下,主线程将等到子线程完成。 But in AJAX the main thread continues its operation...that is what i want 但是在AJAX中,主线程继续运行......这就是我想要的

You could use an ExecutorService to do tasks on the background and then use the methods of the Future you get back to wait for the result. 您可以使用ExecutorService在后台执行任务,然后使用Future返回的方法等待结果。 For example: 例如:

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;
      }
    });
  }
}

In the example above, the main thread will block until the first computation is done, then print it. 在上面的示例中,主线程将阻塞,直到第一次计算完成,然后打印它。 Then block until the second computation is done, then print it, etc. 然后阻止,直到第二次计算完成,然后打印,等等。

If you wish to print the results as they become available (in an unspecified order), then you could use a CompletionService , and instead of having a list of results and iterating on it, you'd get your futures from the CompletionService itself through its .take() method, that blocks until a computation is finished, or .poll() , which returns a Future if there there are finished computations, or null if there are no computations finished -- this way your main thread will never block. 如果您希望在结果可用时(以未指定的顺序)打印结果,那么您可以使用CompletionService ,而不是拥有结果列表并迭代它,您将从CompletionService本身通过其获得您的未来.take()方法,阻塞直到计算完成,或.poll() ,如果有完成计算则返回Future;如果没有计算完成则返回null - 这样你的主线程永远不会阻塞。

The following example uses a CompletionService . 以下示例使用CompletionService It shows a main thread that never blocks, uses background threads to do calculations and process the results as they become available: 它显示了一个永不阻塞的主线程,使用后台线程进行计算并在结果可用时处理结果:

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