public AsyncDiskService(String[] volumes) {
    
    threadFactory = new ThreadFactory() {
      @Override
      public Thread newThread(Runnable r) {
        return new Thread(threadGroup, r);
      }
    };
    
    // Create one ThreadPool per volume
    for (int v = 0 ; v < volumes.length; v++) {
      ThreadPoolExecutor executor = new ThreadPoolExecutor(
          CORE_THREADS_PER_VOLUME, MAXIMUM_THREADS_PER_VOLUME, 
          THREADS_KEEP_ALIVE_SECONDS, TimeUnit.SECONDS, 
          new LinkedBlockingQueue<Runnable>(), threadFactory);

      // This can reduce the number of running threads
      executor.allowCoreThreadTimeOut(true);
      executors.put(volumes[v], executor);
    }
    
  }
@Test
  public void testAsyncDiskService() throws Throwable {
  
    String[] vols = new String[]{"/0", "/1"};
    AsyncDiskService service = new AsyncDiskService(vols);
    
    int total = 100;
    
    for (int i = 0; i < total; i++) {
      service.execute(vols[i%2], new ExampleTask());
    }

    Exception e = null;
    try {
      service.execute("no_such_volume", new ExampleTask());
    } catch (RuntimeException ex) {
      e = ex;
    }
    assertNotNull("Executing a task on a non-existing volume should throw an "
        + "Exception.", e);
    
    service.shutdown();
    if (!service.awaitTermination(5000)) {
      fail("AsyncDiskService didn't shutdown in 5 seconds.");
    }
    
    assertEquals(total, count);
  }