簡體   English   中英

如何使用ExecutorService管理未知數量的Callables的返回值?

[英]How to manage return values of an unknown amount of Callables using ExecutorService?

我想創建一個具有固定線程池大小的singleton-ExecutorService。 另一個線程將給ExecutorService提供Callables,我想在執行完成后立即(優化)解析Callables的結果。

我真的不確定如何正確執行此操作。 我最初的想法是單例ES中的一種方法,該方法通過“ submit(callable)”向ExecutorService添加了Callable並將其存儲在單例內部的HashMap或ArrayList中。 另一個線程將檢查給定時間間隔內的期貨結果。

但是以某種方式,這種解決方案並不“感覺正確”,並且我在其他地方都沒有找到針對該用例的解決方案,因此我要問你們,在我編寫稍后后悔的東西之前。 您將如何解決這個問題?

我期待您的回復!

您可以使用MoreExecutors.listeningDecorator(Executors.newFixedThreadPool(THREAD_NUMBER)); 創建服務並使用番石榴ListenableFuture即時解析結果,您也可以將自行車加長以獲取Listen未來的結果。

ListeningExecutorService service = MoreExecutors.listeningDecorator(Executors.newFixedThreadPool(10));
ListenableFuture<Explosion> explosion = service.submit(new Callable<Explosion>() {
  public Explosion call() {
    return pushBigRedButton();
  }
});
Futures.addCallback(explosion, new FutureCallback<Explosion>() {
  // we want this handler to run immediately after we push the big red button!
  public void onSuccess(Explosion explosion) {
    walkAwayFrom(explosion);
  }
  public void onFailure(Throwable thrown) {
    battleArchNemesis(); // escaped the explosion!
  }
});
import java.util.concurrent.*;

public class PostProcExecutor extends ThreadPoolExecutor {

  // adjust the constructor to your desired threading policy
  public PostProcExecutor(int corePoolSize, int maximumPoolSize,
      long keepAliveTime, TimeUnit unit, BlockingQueue<Runnable> workQueue) {
    super(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue);
  }

  @Override
  protected <T> RunnableFuture<T> newTaskFor(Callable<T> callable) {
    return new FutureTask<T>(callable) {
      @Override
      protected void done()
      {
        if(!isCancelled()) try {
          processResult(get());
        } catch(InterruptedException ex) {
          throw new AssertionError("on complete task", ex);
        } catch(ExecutionException ex) {
          // no result available
        }
      }
    };
  }

  protected void processResult(Object o)
  {
    System.out.println("Result "+o);// do your post-processing here
  }
}

使用ExecutorCompletionService 這樣,您可以在Callable對象准備好后立即獲得它們的結果。 完成服務的take方法阻止等待每個任務完成。

這是來自Java文檔的示例:

void solve(Executor e,
            Collection<Callable<Result>> solvers)
     throws InterruptedException, ExecutionException {
     CompletionService<Result> ecs
         = new ExecutorCompletionService<Result>(e);
     for (Callable<Result> s : solvers)
         ecs.submit(s);
     int n = solvers.size();
     for (int i = 0; i < n; ++i) {
         Result r = ecs.take().get();
         if (r != null)
             use(r);
     }
 }

您可以使用ExecutorCompletionService來實現它。

以下步驟可以為您提供一些幫助。

  1. 使用Runtime.getRuntime()。availableProcessors()填充可用處理器的數量。 讓我們將值保留在變量availableProcessors中。

  2. 初始化ExecutorService,例如service = Executors.newFixedThreadPool(availableProcessors)

  3. 初始化ExecutorCompletionService,假設Callable的結果是Integer Array Integer [], ExecutorCompletionServicecompleteService = new ExecutorCompletionService(service)

  4. 使用completionService.submit提交任務。

  5. 使用completionService.take()。get()獲取任務的每個結果(可調用)。

根據上述步驟,您可以獲得所有可調用的結果,並且可以做一些您想做的事情。

暫無
暫無

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

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