Simplified the task scheduler configuration and exposed setters/constructors for ScheduledExecutorService (INT-113).

This commit is contained in:
Mark Fisher
2008-02-18 22:58:45 +00:00
parent 69b13fc3bf
commit d9d15cab76
8 changed files with 115 additions and 158 deletions

View File

@@ -17,6 +17,7 @@
package org.springframework.integration.adapter;
import java.util.Collection;
import java.util.concurrent.Executors;
import org.springframework.context.Lifecycle;
import org.springframework.integration.channel.MessageChannel;
@@ -97,9 +98,7 @@ public class PollingSourceAdapter<T> extends AbstractSourceAdapter<T> implements
if (logger.isInfoEnabled()) {
logger.info("no task scheduler has been provided, will create one");
}
SimpleMessagingTaskScheduler taskScheduler = new SimpleMessagingTaskScheduler();
taskScheduler.setCorePoolSize(1);
this.scheduler = taskScheduler;
this.scheduler = new SimpleMessagingTaskScheduler(Executors.newSingleThreadScheduledExecutor());
}
if (!this.scheduler.isRunning()) {
this.scheduler.start();

View File

@@ -20,6 +20,8 @@ import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.CopyOnWriteArrayList;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.ScheduledThreadPoolExecutor;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
@@ -47,7 +49,6 @@ import org.springframework.integration.scheduling.MessagingTaskSchedulerAware;
import org.springframework.integration.scheduling.Schedule;
import org.springframework.integration.scheduling.SimpleMessagingTaskScheduler;
import org.springframework.integration.scheduling.Subscription;
import org.springframework.scheduling.concurrent.CustomizableThreadFactory;
import org.springframework.util.Assert;
/**
@@ -58,21 +59,24 @@ import org.springframework.util.Assert;
*/
public class MessageBus implements ChannelRegistry, ApplicationContextAware, Lifecycle {
private Log logger = LogFactory.getLog(this.getClass());
private static final int DEFAULT_DISPATCHER_POOL_SIZE = 10;
private ChannelRegistry channelRegistry = new DefaultChannelRegistry();
private Map<String, MessageEndpoint> endpoints = new ConcurrentHashMap<String, MessageEndpoint>();
private final Log logger = LogFactory.getLog(this.getClass());
private Map<MessageChannel, SchedulingMessageDispatcher> dispatchers = new ConcurrentHashMap<MessageChannel, SchedulingMessageDispatcher>();
private final ChannelRegistry channelRegistry = new DefaultChannelRegistry();
private List<Lifecycle> lifecycleSourceAdapters = new CopyOnWriteArrayList<Lifecycle>();
private final Map<String, MessageEndpoint> endpoints = new ConcurrentHashMap<String, MessageEndpoint>();
private MessagingTaskScheduler taskScheduler;
private final Map<MessageChannel, SchedulingMessageDispatcher> dispatchers = new ConcurrentHashMap<MessageChannel, SchedulingMessageDispatcher>();
private int dispatcherPoolSize = 10;
private final List<Lifecycle> lifecycleSourceAdapters = new CopyOnWriteArrayList<Lifecycle>();
private boolean autoCreateChannels;
private volatile MessagingTaskScheduler taskScheduler;
private volatile ScheduledExecutorService executor;
private volatile boolean autoCreateChannels;
private volatile boolean autoStartup = true;
@@ -82,7 +86,7 @@ public class MessageBus implements ChannelRegistry, ApplicationContextAware, Lif
private volatile boolean running;
private Object lifecycleMonitor = new Object();
private final Object lifecycleMonitor = new Object();
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
@@ -99,23 +103,11 @@ public class MessageBus implements ChannelRegistry, ApplicationContextAware, Lif
}
}
public void setMessagingTaskScheduler(MessagingTaskScheduler taskScheduler) {
Assert.notNull(taskScheduler, "task scheduler must not be null");
if (taskScheduler instanceof SimpleMessagingTaskScheduler) {
((SimpleMessagingTaskScheduler) taskScheduler).setCorePoolSize(dispatcherPoolSize);
}
this.taskScheduler = taskScheduler;
}
/**
* Set the size for the dispatcher thread pool.
* Set the {@link ScheduledExecutorService} to use for scheduling message dispatchers.
*/
public void setDispatcherPoolSize(int dispatcherPoolSize) {
Assert.isTrue(dispatcherPoolSize > 0, "'dispatcherPoolSize' must be at least 1");
this.dispatcherPoolSize = dispatcherPoolSize;
if (this.taskScheduler != null && this.taskScheduler instanceof SimpleMessagingTaskScheduler) {
((SimpleMessagingTaskScheduler) this.taskScheduler).setCorePoolSize(dispatcherPoolSize);
}
public void setScheduledExecutorService(ScheduledExecutorService executor) {
this.executor = executor;
}
/**
@@ -170,25 +162,16 @@ public class MessageBus implements ChannelRegistry, ApplicationContextAware, Lif
if (this.getErrorChannel() == null) {
this.setErrorChannel(new SimpleChannel(Integer.MAX_VALUE));
}
if (this.taskScheduler == null) {
this.setMessagingTaskScheduler(createDefaultScheduler());
if (this.executor == null) {
this.executor = new ScheduledThreadPoolExecutor(DEFAULT_DISPATCHER_POOL_SIZE);
}
SimpleMessagingTaskScheduler scheduler = new SimpleMessagingTaskScheduler(this.executor);
scheduler.setErrorHandler(new MessagePublishingErrorHandler(this.getErrorChannel()));
this.taskScheduler = scheduler;
this.initialized = true;
}
}
private MessagingTaskScheduler createDefaultScheduler() {
CustomizableThreadFactory threadFactory = new CustomizableThreadFactory();
threadFactory.setThreadNamePrefix("dispatcher-executor-");
threadFactory.setThreadGroup(new ThreadGroup("dispatcher-executors"));
SimpleMessagingTaskScheduler scheduler = new SimpleMessagingTaskScheduler();
scheduler.setCorePoolSize(this.dispatcherPoolSize);
scheduler.setThreadFactory(threadFactory);
scheduler.setErrorHandler(new MessagePublishingErrorHandler(this.getErrorChannel()));
scheduler.afterPropertiesSet();
return scheduler;
}
public MessageChannel getErrorChannel() {
return this.channelRegistry.getErrorChannel();
}
@@ -206,8 +189,7 @@ public class MessageBus implements ChannelRegistry, ApplicationContextAware, Lif
this.initialize();
}
channel.setName(name);
DefaultMessageDispatcher dispatcher = new DefaultMessageDispatcher(channel);
dispatcher.setMessagingTaskScheduler(this.taskScheduler);
DefaultMessageDispatcher dispatcher = new DefaultMessageDispatcher(channel, this.taskScheduler);
this.dispatchers.put(channel, dispatcher);
this.channelRegistry.registerChannel(name, channel);
if (logger.isInfoEnabled()) {

View File

@@ -27,15 +27,14 @@ import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.context.Lifecycle;
import org.springframework.integration.MessagingConfigurationException;
import org.springframework.integration.channel.MessageChannel;
import org.springframework.integration.handler.MessageHandler;
import org.springframework.integration.message.Message;
import org.springframework.integration.scheduling.MessagingTask;
import org.springframework.integration.scheduling.MessagingTaskScheduler;
import org.springframework.integration.scheduling.MessagingTaskSchedulerAware;
import org.springframework.integration.scheduling.PollingSchedule;
import org.springframework.integration.scheduling.Schedule;
import org.springframework.integration.scheduling.SimpleMessagingTaskScheduler;
import org.springframework.util.Assert;
/**
@@ -47,7 +46,7 @@ import org.springframework.util.Assert;
*
* @author Mark Fisher
*/
public class DefaultMessageDispatcher implements SchedulingMessageDispatcher, MessagingTaskSchedulerAware {
public class DefaultMessageDispatcher implements SchedulingMessageDispatcher {
protected final Log logger = LogFactory.getLog(this.getClass());
@@ -55,33 +54,28 @@ public class DefaultMessageDispatcher implements SchedulingMessageDispatcher, Me
private final MessageRetriever retriever;
private MessagingTaskScheduler scheduler;
private final MessagingTaskScheduler scheduler;
private Schedule defaultSchedule = new PollingSchedule(5);
private volatile Schedule defaultSchedule = new PollingSchedule(5);
private final ConcurrentMap<Schedule, List<MessageHandler>> scheduledHandlers = new ConcurrentHashMap<Schedule, List<MessageHandler>>();
private final AtomicLong totalMessagesProcessed = new AtomicLong();
private volatile boolean starting;
private volatile boolean running;
private final Object lifecycleMonitor = new Object();
public DefaultMessageDispatcher(MessageChannel channel) {
public DefaultMessageDispatcher(MessageChannel channel, MessagingTaskScheduler scheduler) {
Assert.notNull(channel, "'channel' must not be null");
Assert.notNull(scheduler, "'scheduler' must not be null");
this.channel = channel;
this.scheduler = scheduler;
this.retriever = new ChannelPollingMessageRetriever(this.channel);
}
public void setMessagingTaskScheduler(MessagingTaskScheduler scheduler) {
Assert.notNull(scheduler, "'scheduler' must not be null");
this.scheduler = scheduler;
}
public void setDefaultSchedule(Schedule defaultSchedule) {
Assert.notNull(defaultSchedule, "'defaultSchedule' must not be null");
this.defaultSchedule = defaultSchedule;
@@ -123,33 +117,23 @@ public class DefaultMessageDispatcher implements SchedulingMessageDispatcher, Me
public void start() {
synchronized (this.lifecycleMonitor) {
if (this.isRunning() || this.starting) {
if (this.running) {
return;
}
this.starting = true;
}
if (this.scheduler == null) {
if (logger.isInfoEnabled()) {
logger.info("no scheduler was provided, will create one");
if (this.scheduler == null) {
throw new MessagingConfigurationException("'scheduler' is required");
}
if (!this.scheduler.isRunning()) {
this.scheduler.start();
}
this.scheduler = new SimpleMessagingTaskScheduler();
}
if (!this.scheduler.isRunning()) {
this.scheduler.start();
}
synchronized (this.lifecycleMonitor) {
for (Schedule schedule : this.scheduledHandlers.keySet()) {
scheduleDispatcherTask(schedule);
}
this.running = true;
this.starting = false;
}
}
private void scheduleDispatcherTask(Schedule schedule) {
if (!this.isRunning()) {
this.start();
}
List<MessageHandler> handlers = this.scheduledHandlers.get(schedule);
for (MessageHandler handler : handlers) {
if (handler instanceof Lifecycle) {
@@ -160,7 +144,7 @@ public class DefaultMessageDispatcher implements SchedulingMessageDispatcher, Me
}
public void stop() {
if (!this.isRunning()) {
if (!this.running) {
return;
}
synchronized (this.lifecycleMonitor) {

View File

@@ -21,12 +21,9 @@ import java.util.concurrent.CopyOnWriteArraySet;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.ScheduledFuture;
import java.util.concurrent.ScheduledThreadPoolExecutor;
import java.util.concurrent.ThreadFactory;
import java.util.concurrent.TimeUnit;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.integration.util.ErrorHandler;
import org.springframework.scheduling.concurrent.CustomizableThreadFactory;
import org.springframework.util.Assert;
/**
@@ -35,78 +32,60 @@ import org.springframework.util.Assert;
*
* @author Mark Fisher
*/
public class SimpleMessagingTaskScheduler extends AbstractMessagingTaskScheduler implements InitializingBean {
public class SimpleMessagingTaskScheduler extends AbstractMessagingTaskScheduler {
private ScheduledExecutorService executor;
private final ScheduledExecutorService executor;
private int corePoolSize = 10;
private volatile ErrorHandler errorHandler;
private ThreadFactory threadFactory;
private final Set<Runnable> pendingTasks = new CopyOnWriteArraySet<Runnable>();
private String threadNamePrefix = this.getClass().getSimpleName() + "-";
private ErrorHandler errorHandler;
private Set<Runnable> pendingTasks = new CopyOnWriteArraySet<Runnable>();
private volatile boolean starting;
private volatile boolean running;
private Object lifecycleMonitor = new Object();
private final Object lifecycleMonitor = new Object();
public void setExecutor(ScheduledExecutorService executor) {
public SimpleMessagingTaskScheduler(int corePoolSize) {
this(new ScheduledThreadPoolExecutor(corePoolSize));
}
public SimpleMessagingTaskScheduler(ScheduledExecutorService executor) {
Assert.notNull(executor, "'executor' must not be null");
this.executor = executor;
}
public void setCorePoolSize(int corePoolSize) {
Assert.isTrue(corePoolSize > 0, "'corePoolSize' must be greater than 0");
this.corePoolSize = corePoolSize;
}
public void setThreadFactory(ThreadFactory threadFactory) {
this.threadFactory = threadFactory;
}
public void setThreadNamePrefix(String threadNamePrefix) {
Assert.notNull(threadNamePrefix, "'threadNamePrefix' must not be null");
this.threadNamePrefix = threadNamePrefix;
}
public void setErrorHandler(ErrorHandler errorHandler) {
this.errorHandler = errorHandler;
}
public void afterPropertiesSet() {
if (this.executor == null) {
if (this.threadFactory == null) {
this.threadFactory = new CustomizableThreadFactory(this.threadNamePrefix);
}
this.executor = new ScheduledThreadPoolExecutor(this.corePoolSize, this.threadFactory);
}
}
public boolean isRunning() {
return this.running;
}
public void start() {
if (this.executor == null) {
this.afterPropertiesSet();
}
synchronized (this.lifecycleMonitor) {
this.running = true;
for (Runnable task : this.pendingTasks) {
this.schedule(task);
if (this.running || this.starting) {
return;
}
this.pendingTasks.clear();
this.starting = true;
}
for (Runnable task : this.pendingTasks) {
this.schedule(task);
}
this.pendingTasks.clear();
this.running = true;
this.starting = false;
}
public void stop() {
if (this.isRunning()) {
this.running = false;
this.executor.shutdownNow();
synchronized (this.lifecycleMonitor) {
if (this.running) {
this.executor.shutdownNow();
this.running = false;
}
}
}