package org.atomnuke.task.threading;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Future;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.ThreadFactory;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicLong;
import org.atomnuke.NukeEnvironment;
import org.atomnuke.kernel.NukeRejectionHandler;
import org.atomnuke.kernel.NukeThreadPoolExecutor;
import org.atomnuke.util.TimeValue;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
*
* @author zinic
*/
public class ExecutionQueueImpl implements ExecutionQueue {
private static final AtomicLong TID = new AtomicLong(0);
private static final ThreadFactory DEFAULT_THREAD_FACTORY = new ThreadFactory() {
@Override
public Thread newThread(Runnable r) {
return new Thread(r, "nuke-worker-" + TID.incrementAndGet());
}
};
private static final TimeValue DEFAULT_THREAD_KEEPALIVE = new TimeValue(30, TimeUnit.SECONDS);
private static final Logger LOG = LoggerFactory.getLogger(ExecutionQueueImpl.class);
private static final int DEFAULT_QUEUE_SIZE = 256000;
private final BlockingQueue<Runnable> executionQueue;
private final ExecutorService executorService;
public ExecutionQueueImpl(NukeEnvironment nukeEnvironment) {
this(nukeEnvironment.numProcessors(), nukeEnvironment.numProcessors() * 2);
}
/**
*
* @param corePoolSize sets the number of threads that the execution pool
* will retain during normal operation.
* @param maxPoolsize sets the maximum number of threads that the execution
* pool may spawn.
*/
public ExecutionQueueImpl(int corePoolSize, int maxPoolSize) {
executionQueue = new LinkedBlockingQueue<Runnable>();
executorService = new NukeThreadPoolExecutor(corePoolSize, maxPoolSize, DEFAULT_THREAD_KEEPALIVE, executionQueue, DEFAULT_THREAD_FACTORY, new NukeRejectionHandler());
}
@Override
public void destroy() {
LOG.info("Clearing: " + executionQueue.size() + " scheduled tasks");
// Clear any scheduled tasks
executionQueue.clear();
// Shutdown our executor service
executorService.shutdown();
try {
// Try to wait for things to settle
executorService.awaitTermination(5, TimeUnit.SECONDS);
} catch (InterruptedException ie) {
LOG.error("Interrupted while waiting for task delegates to finish. This may introduce bad state.", ie);
executorService.shutdownNow();
}
}
@Override
public boolean isFull() {
return executionQueue.size() > DEFAULT_QUEUE_SIZE;
}
@Override
public Future submit(Runnable r) {
return executorService.submit(r);
}
@Override
public <T> Future<T> submit(Runnable r, T stateObject) {
return submit(r, stateObject);
}
}