X-Git-Url: https://git.opendaylight.org/gerrit/gitweb?a=blobdiff_plain;f=common%2Futil%2Fsrc%2Fmain%2Fjava%2Forg%2Fopendaylight%2Fyangtools%2Futil%2FExecutorServiceUtil.java;h=c6a933ab0d2fde82185a0436418430b1413c9664;hb=4f66528ebcf1603108218b8ebf48147d8ed3ad38;hp=36f729fb8ff69210e475ad67f8466f3dd973f5f0;hpb=cba18b8c8be59973f7d1b44a116f4ff1a0623183;p=yangtools.git diff --git a/common/util/src/main/java/org/opendaylight/yangtools/util/ExecutorServiceUtil.java b/common/util/src/main/java/org/opendaylight/yangtools/util/ExecutorServiceUtil.java index 36f729fb8f..c6a933ab0d 100644 --- a/common/util/src/main/java/org/opendaylight/yangtools/util/ExecutorServiceUtil.java +++ b/common/util/src/main/java/org/opendaylight/yangtools/util/ExecutorServiceUtil.java @@ -7,42 +7,47 @@ */ package org.opendaylight.yangtools.util; +import com.google.common.util.concurrent.ForwardingBlockingQueue; import java.util.concurrent.BlockingQueue; import java.util.concurrent.ExecutorService; import java.util.concurrent.RejectedExecutionException; import java.util.concurrent.RejectedExecutionHandler; import java.util.concurrent.ThreadPoolExecutor; - +import java.util.concurrent.TimeUnit; +import org.eclipse.jdt.annotation.NonNull; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import com.google.common.util.concurrent.ForwardingBlockingQueue; - /** * Utility methods for dealing with {@link ExecutorService}s. */ public final class ExecutorServiceUtil { private static final class WaitInQueueExecutionHandler implements RejectedExecutionHandler { @Override + @SuppressWarnings("checkstyle:parameterName") public void rejectedExecution(final Runnable r, final ThreadPoolExecutor executor) { + if (executor.isShutdown()) { + throw new RejectedExecutionException("Executor has been shutdown."); + } + try { executor.getQueue().put(r); } catch (InterruptedException e) { - LOG.debug("Intterupted while waiting for queue", e); - throw new RejectedExecutionException("Interrupted while waiting for queue", e); + LOG.debug("Interrupted while attempting to put to the queue", e); + throw new RejectedExecutionException("Interrupted while attempting to put to the queue", e); } } } private static final Logger LOG = LoggerFactory.getLogger(ExecutorServiceUtil.class); - private static final RejectedExecutionHandler WAIT_IN_QUEUE_HANDLER = new WaitInQueueExecutionHandler(); + private static final @NonNull RejectedExecutionHandler WAIT_IN_QUEUE_HANDLER = new WaitInQueueExecutionHandler(); private ExecutorServiceUtil() { - throw new UnsupportedOperationException("Utility class"); + // Hidden on purpose } /** - * Create a {@link BlockingQueue} which does not allow for non-blocking addition to the queue. + * Creates a {@link BlockingQueue} which does not allow for non-blocking addition to the queue. * This is useful with {@link #waitInQueueExecutionHandler()} to turn force a * {@link ThreadPoolExecutor} to create as many threads as it is configured to before starting * to fill the queue. @@ -50,9 +55,10 @@ public final class ExecutorServiceUtil { * @param delegate Backing blocking queue. * @return A new blocking queue backed by the delegate */ - public BlockingQueue offerFailingBlockingQueue(final BlockingQueue delegate) { - return new ForwardingBlockingQueue() { + public static @NonNull BlockingQueue offerFailingBlockingQueue(final BlockingQueue delegate) { + return new ForwardingBlockingQueue<>() { @Override + @SuppressWarnings("checkstyle:parameterName") public boolean offer(final E o) { return false; } @@ -65,12 +71,30 @@ public final class ExecutorServiceUtil { } /** - * Return a {@link RejectedExecutionHandler} which blocks on the {@link ThreadPoolExecutor}'s + * Returns a {@link RejectedExecutionHandler} which blocks on the {@link ThreadPoolExecutor}'s * backing queue if a new thread cannot be spawned. * * @return A shared RejectedExecutionHandler instance. */ - public RejectedExecutionHandler waitInQueueExecutionHandler() { + public static @NonNull RejectedExecutionHandler waitInQueueExecutionHandler() { return WAIT_IN_QUEUE_HANDLER; } + + /** + * Tries to shutdown the given executor gracefully by awaiting termination for the given + * timeout period. If the timeout elapses before termination, the executor is forcefully + * shutdown. + */ + public static void tryGracefulShutdown(final @NonNull ExecutorService executor, final long timeout, + final @NonNull TimeUnit unit) { + executor.shutdown(); + + try { + if (!executor.awaitTermination(timeout, unit)) { + executor.shutdownNow(); + } + } catch (InterruptedException e) { + executor.shutdownNow(); + } + } }