Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.
Comment: added NCE/CS for thread pool shutdown problems

...

Code Block
bgColor#ccccff
class PoolService {
  private final ExecutorService pool;

  public PoolService(int poolSize) {
    pool = Executors.newFixedThreadPool(poolSize);
  }
  
  public void doSomething() throws InterruptedException {
    Future<?> future = null;
    try {
      future = pool.submit(new Task());
      // ...
    } catch(Throwable t) {
      future.cancel(true);
      // Forward to handler
    }
  }
}

Noncompliant Code Example (shutting down thread pools)

Wiki Markup
According to the Java API \[[API 06|AA. Java References#API 06]\], interface {{java.util.concurrent.ExecutorService}}, method {{shutdownNow()}} documentation:

Attempts to stop all actively executing tasks, halts the processing of waiting tasks, and returns a list of the tasks that were awaiting execution. There are no guarantees beyond best-effort attempts to stop processing actively executing tasks. For example, typical implementations will cancel via Thread.interrupt(), so any task that fails to respond to interrupts may never terminate.

This noncompliant code example uses the SocketReader class defined earlier in Compliant Solution (close socket connection) and submits it as a task to a thread pool defined in class PoolService.

Code Block
bgColor#FFcccc

class PoolService {
  private final ExecutorService pool;

  public PoolService(int poolSize) {
    pool = Executors.newFixedThreadPool(poolSize);
  }
	  
  public void doSomething() throws InterruptedException, IOException {	   
    pool.submit(new SocketReader());
    // ...
    List<Runnable> awaitingTasks = pool.shutdownNow();	      
  }

  public static void main(String[] args) throws InterruptedException, IOException {
    PoolService service = new PoolService(5);
    service.doSomething();
  }
}

class SocketReader implements Runnable {
  private final Socket socket;
  // ...
}

Because the task does not support interruption through the use of Thread.interrupted(), there is no guarantee that the shutdownNow() method will shutdown the thread pool. Using the shutdown() method does not fix the problem either because it waits until all executing tasks have finished. Likewise, tasks that check a volatile flag to determine whether it is safe to shutdown are not responsive to these methods.

Compliant Solution (submit interruptible tasks)

Tasks that do not support interruption using Thread.interrupt() should not be submitted to a thread pool. This compliant solution submits the interruptible version of SocketReader discussed in Compliant Solution (interruptible channel) to the thread pool.

Code Block
bgColor#ccccff

class PoolService {
  // ...
}

class SocketReader implements Runnable {
  private final SocketChannel sc;
  // ...
}

Risk Assessment

Trying to force thread shutdown can result in inconsistent object state and corrupt the object. Critical resources may also leak if cleanup operations are not carried out as required.

...

Wiki Markup
\[[API 06|AA. Java References#API 06]\] Class Thread, method {{stop}}, interface ExecutorService
\[[Darwin 04|AA. Java References#Darwin 04]\] 24.3 Stopping a Thread
\[[JDK7 08|AA. Java References#JDK7 08]\] Concurrency Utilities, More information: Java Thread Primitive Deprecation 
\[[JPL 06|AA. Java References#JPL 06]\] 14.12.1. Don't stop and 23.3.3. Shutdown Strategies
\[[JavaThreads 04|AA. Java References#JavaThreads 04]\] 2.4 Two Approaches to Stopping a Thread
\[[Goetz 06|AA. Java References#Goetz 06]\] Chapter 7: Cancellation and shutdown

...