Java ThreadPoolExecutor将线程释放到线程池

时间:2014-11-18 00:50:53

标签: java scala executor

我有以下Runnable.run()方法:

public void run() {
    calculateStuff();
    boolean ioSuccesful = IOforThisRunnable();   
    while(!ioSuccesful ) {
        Thread.sleep(500);   // alternative?
        boolean ioSuccesful = IOforThisRunnable();
    }  
}

我想在具有最大线程数的ThreadPoolExecutor中执行此代码。

现在我的问题:

假设我的线程池包含5个线程。在当前示例中,5个runnables将阻止执行任何其他线程,因为Thread.sleep()不会释放线程?! (如果IO不成功)

有没有办法释放线程而不是使用Thread.sleep(),以便其他runnable可以开始执行而另一个正在等待IO?

那么在最坏的情况下,所有runnable都会坐在while循环中?

1 个答案:

答案 0 :(得分:2)

如果您的I / O工作正在阻塞,那么您别无选择:线程必须位于堆栈上,等待阻塞I / O完成,以便该线程无法执行任何其他工作。

你想要的是使用非阻塞I / O,结合Guava的ListenableFuture之类的东西。这将使您能够执行以下操作:

static ListenableFuture<Boolean> doIoWork() {
  // ...
}

static ListenableFuture<Boolean> doIoWithRetry(
    ListeningExecutorService executor) {
  SettableFuture<Boolean> finalResult = SettableFuture.create();
  calculateStuff();
  doIoWithRetry(executor, finalResult);
  return finalResult;
}

private static void doIoWithRetry(
    final ListeningExecutorService executor,
    final SettableFuture<Boolean> finalResult) {
  final ListenableFuture<Boolean> pendingWork = doIoWork();
  pendingWork.addListener(new Runnable() {
    @Override public void run() {
      // pendingWork is now complete
      // (error checking elided here)
      boolean ioSuccessful = pendingWork.get();
      if (ioSuccessful) {
        finalResult.set(true);
        return;
      }
      doIoWithRetry(executor, finalWork);
    }
  }, executor);
}