package org.oddjob.scheduling;
import java.util.List;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.ScheduledThreadPoolExecutor;
import java.util.concurrent.SynchronousQueue;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
import org.apache.log4j.Logger;
import org.oddjob.OddjobExecutors;
/**
* Provide Simple Oddjob Services.
*
* @author rob
*
*/
public class DefaultExecutors implements OddjobExecutors {
private static final Logger logger = Logger.getLogger(DefaultExecutors.class);
public static final String POOL_SIZE_PROPERTY = "oddjob.executors.default.poolsize";
/** The pool size for the {@link ScheduledExecutorService}. */
private int poolSize;
/** share Executor and Scheduled services. */
private boolean shareServices;
/** The standard executor service. */
private ExecutorService poolExecutorService;
/** The scheduler */
private ScheduledExecutorService scheduledExecutorService;
/**
* Create a new instance. The scheduler is initialised with a
* fixed pool size that is either from the system property
* or based on the number of available processors discovered at
* runtime. The pool size can also be set by the property.
*/
public DefaultExecutors() {
String poolSizeString = System.getProperty(POOL_SIZE_PROPERTY);
if (poolSizeString == null) {
poolSize = Runtime.getRuntime().availableProcessors() + 1;
}
else {
poolSize = Integer.parseInt(poolSizeString);
}
}
/**
* Stop the services.
*/
public void stop() {
ExecutorService scheduledExecutor;
ExecutorService poolExecutor;
synchronized (this) {
scheduledExecutor = scheduledExecutorService;
scheduledExecutorService = null;
poolExecutor = poolExecutorService;
poolExecutorService = null;
}
if (poolExecutor != null) {
logger.info("Shutting down Pool Executor.");
List<Runnable> running = poolExecutor.shutdownNow();
logger.info("Shutdown Pool Exector with " +
running.size() + " unexecuted jobs.");
}
if (scheduledExecutor != null) {
logger.info("Shutting down Scheduled Executor.");
List<Runnable> running = scheduledExecutor.shutdownNow();
logger.info("Shutdown Scheduled Exector with " +
running.size() + " unexecuted jobs.");
}
}
/*
* (non-Javadoc)
* @see org.oddjob.OddjobExecutors#getScheduledExecutor()
*/
public ScheduledExecutorService getScheduledExecutor() {
return startTimerOnFirstRequest();
}
/*
* (non-Javadoc)
* @see org.oddjob.OddjobExecutors#getPoolExecutor()
*/
public ExecutorService getPoolExecutor() {
if (shareServices) {
return getScheduledExecutor();
}
else {
return startPoolExecutorOnFirstRequest();
}
}
/**
* Provide lazy service starting.
*
* @return The scheduled executor service.
*/
private synchronized ScheduledExecutorService startTimerOnFirstRequest() {
if (scheduledExecutorService == null) {
logger.info("Starting Scheduled Exector with " + poolSize + " threads.");
scheduledExecutorService = new OddjobScheduledExecutorService(
new ScheduledThreadPoolExecutor(poolSize));
}
return scheduledExecutorService;
}
/**
* Provide lazy starting of a pool executor.
*
* @return The executor service.
*/
private synchronized ExecutorService startPoolExecutorOnFirstRequest() {
if (poolExecutorService == null) {
logger.info("Starting Pool Executor.");
poolExecutorService = new OddjobExecutorService(
new ThreadPoolExecutor(0, Integer.MAX_VALUE,
60L, TimeUnit.SECONDS,
new SynchronousQueue<Runnable>()));
}
return poolExecutorService;
}
/**
* Get the pool size for the scheduled executor.
*
* @return
*/
public int getPoolSize() {
return poolSize;
}
/**
* Set the pool size for the scheduled executor.
*
* @param poolSize The pool size.
*/
public void setPoolSize(int poolSize) {
this.poolSize = poolSize;
}
public boolean isShareServices() {
return shareServices;
}
/**
* Share the same service between the executor service and the scheduled
* executor service.
*
* @param shareServices
*/
public void setShareServices(boolean shareServices) {
this.shareServices = shareServices;
}
@Override
public String toString() {
return getClass().getSimpleName() + " (" +
((poolExecutorService == null &&
scheduledExecutorService == null) ? "not started" : "started") +
")";
}
}