Java ThreadPoolExecutor release thread to thread pool

1.7k views Asked by At

I have the following Runnable.run() method:

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

I want to execute this code in a ThreadPoolExecutor with a maximum number of Threads.

Now for my question:

Suppose my threadpool consist of 5 threads. In the current example 5 runnables would block execution for any additional Threads since Thread.sleep() does not release the thread?! (if IO is not succesful)

Is there any way to release the thread instead of using Thread.sleep() so that other runnables can start executing while another is waiting for IO?

So that in the worst case scenario all runnables would be sitting in while loop?

1

There are 1 answers

1
Daniel Pryden On BEST ANSWER

If your I/O work is blocking, then you have no choice: the thread has to be sitting around on the stack waiting for the blocking I/O to complete, so that thread can't be doing any other work.

What you want is to use non-blocking I/O, combined with something like Guava's ListenableFuture. This would enable you to do something like:

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