ExecutorCloser implements Closeable { @Override public void close() { if (executorService == null) { return; } try { executorService.shutdown(); executorService.awaitTermination(timeout, timeUnit); } catch (InterruptedException e) { LOG.error("Error while shutting down the ExecutorService", e); Thread.currentThread().interrupt(); } finally { if (!executorService.isShutdown()) { LOG.warn("ExecutorService `{}` didn't shutdown property. Will be forced now.", executorService); } executorService.shutdownNow(); } } ExecutorCloser(@Nullable ExecutorService executorService);  ExecutorCloser(@Nullable ExecutorService executorService, int timeout, TimeUnit unit); @Override void close();  }
@Test public void simple() throws Exception{ ExecutorService executorService = Executors.newSingleThreadExecutor(); assertFalse(executorService.isTerminated()); new ExecutorCloser(executorService).close(); assertTrue(executorService.isTerminated()); }
@Test public void nullExecutor() throws Exception{ new ExecutorCloser(null).close(); }
@Test public void timeoutHandling() throws Exception{ ExecutorService executorService = Executors.newSingleThreadExecutor(); final CountDownLatch latch = new CountDownLatch(1); executorService.submit(new Callable<Void>() { @Override public Void call() throws Exception { latch.await(); return null; } }); new ExecutorCloser(executorService, 100, TimeUnit.MILLISECONDS).close(); assertTrue(executorService.isShutdown()); }