/*
* Copyright (c) 2014 Cisco Systems, Inc. and others. All rights reserved.
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License v1.0 which accompanies this distribution,
* and is available at http://www.eclipse.org/legal/epl-v10.html
*/
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 javax.annotation.Nonnull;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* Utility methods for dealing with {@link ExecutorService}s.
*/
public final class ExecutorServiceUtil {
private static final class WaitInQueueExecutionHandler implements RejectedExecutionHandler {
@Override
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("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 ExecutorServiceUtil() {
throw new UnsupportedOperationException("Utility class");
}
/**
* 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.
*
* @param delegate Backing blocking queue.
* @return A new blocking queue backed by the delegate
*/
public static <E> BlockingQueue<E> offerFailingBlockingQueue(final BlockingQueue<E> delegate) {
return new ForwardingBlockingQueue<E>() {
@Override
public boolean offer(@Nonnull final E o) {
return false;
}
@Override
protected BlockingQueue<E> delegate() {
return delegate;
}
};
}
/**
* 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 static 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 ExecutorService executor, long timeout,
TimeUnit unit ) {
executor.shutdown();
try {
if (!executor.awaitTermination(timeout, unit)) {
executor.shutdownNow();
}
} catch (InterruptedException e) {
executor.shutdownNow();
}
}
}