Refactored ConcurrentHandler to accept a preconfigured ExecutorService rather than creating one from the ConcurrencyPolicy.

This commit is contained in:
Mark Fisher
2008-02-18 17:46:23 +00:00
parent 3d1303bb53
commit 0b5013939e
4 changed files with 71 additions and 134 deletions

View File

@@ -17,7 +17,13 @@
package org.springframework.integration.endpoint;
import java.util.List;
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.CopyOnWriteArrayList;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.SynchronousQueue;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
import org.springframework.beans.factory.BeanNameAware;
import org.springframework.beans.factory.InitializingBean;
@@ -156,14 +162,19 @@ public class DefaultMessageEndpoint implements MessageEndpoint, ChannelRegistryA
public void afterPropertiesSet() {
if (this.concurrencyPolicy != null || this.handler instanceof ConcurrentHandler) {
if (!(this.handler instanceof ConcurrentHandler)) {
this.handler = new ConcurrentHandler(this.handler, this.concurrencyPolicy);
int capacity = concurrencyPolicy.getQueueCapacity();
BlockingQueue<Runnable> queue = (capacity < 1) ? new SynchronousQueue<Runnable>() :
new ArrayBlockingQueue<Runnable>(capacity);
ExecutorService executor = new ThreadPoolExecutor(concurrencyPolicy.getCoreSize(),
concurrencyPolicy.getMaxSize(), concurrencyPolicy.getKeepAliveSeconds(),
TimeUnit.SECONDS, queue);
this.handler = new ConcurrentHandler(this.handler, executor);
}
ConcurrentHandler concurrentHandler = (ConcurrentHandler) this.handler;
if (this.errorHandler != null) {
concurrentHandler.setErrorHandler(this.errorHandler);
}
concurrentHandler.setReplyHandler(this.replyHandler);
concurrentHandler.afterPropertiesSet();
}
this.initialized = true;
}

View File

@@ -16,15 +16,14 @@
package org.springframework.integration.handler;
import java.util.concurrent.ExecutorService;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.context.Lifecycle;
import org.springframework.integration.endpoint.ConcurrencyPolicy;
import org.springframework.beans.factory.DisposableBean;
import org.springframework.integration.message.Message;
import org.springframework.integration.util.ErrorHandler;
import org.springframework.scheduling.concurrent.CustomizableThreadFactory;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
import org.springframework.util.Assert;
@@ -35,50 +34,27 @@ import org.springframework.util.Assert;
*
* @author Mark Fisher
*/
public class ConcurrentHandler implements MessageHandler, Lifecycle, InitializingBean {
public class ConcurrentHandler implements MessageHandler, DisposableBean {
private Log logger = LogFactory.getLog(this.getClass());
private final Log logger = LogFactory.getLog(this.getClass());
private MessageHandler handler;
private final MessageHandler handler;
private ThreadPoolTaskExecutor executor;
private final ExecutorService executor;
private volatile int currentQueueCapacity;
private volatile ErrorHandler errorHandler;
private final ConcurrencyPolicy concurrencyPolicy;
private ErrorHandler errorHandler;
private ReplyHandler replyHandler;
private volatile boolean running;
private Object lifecycleMonitor = new Object();
private volatile ReplyHandler replyHandler;
public ConcurrentHandler(MessageHandler handler) {
this(handler, null);
}
public ConcurrentHandler(MessageHandler handler, ConcurrencyPolicy concurrencyPolicy) {
public ConcurrentHandler(MessageHandler handler, ExecutorService executor) {
Assert.notNull(handler, "'handler' must not be null");
if (concurrencyPolicy != null) {
Assert.isTrue(concurrencyPolicy.getMaxSize() >= concurrencyPolicy.getCoreSize(),
"'coreSize' must not exceed 'maxSize'");
this.concurrencyPolicy = concurrencyPolicy;
}
else {
this.concurrencyPolicy = new ConcurrencyPolicy();
}
this.handler = handler;
}
public void setExecutor(ThreadPoolTaskExecutor executor) {
Assert.notNull(executor, "'executor' must not be null");
this.handler = handler;
this.executor = executor;
}
public void setErrorHandler(ErrorHandler errorHandler) {
this.errorHandler = errorHandler;
}
@@ -87,74 +63,12 @@ public class ConcurrentHandler implements MessageHandler, Lifecycle, Initializin
this.replyHandler = replyHandler;
}
public void afterPropertiesSet() {
refreshExecutor();
}
public void refreshExecutor() {
if (this.executor == null || currentQueueCapacity != this.concurrencyPolicy.getQueueCapacity()) {
this.initializeExecutor();
}
else {
this.refreshRuntimeModifiableExecutorProperties();
}
}
private void initializeExecutor() {
synchronized (this.lifecycleMonitor) {
if (this.executor != null) {
this.executor.shutdown();
}
this.executor = new ThreadPoolTaskExecutor();
this.currentQueueCapacity = this.concurrencyPolicy.getQueueCapacity();
this.executor.setQueueCapacity(this.currentQueueCapacity);
CustomizableThreadFactory threadFactory = new CustomizableThreadFactory();
threadFactory.setThreadNamePrefix("handler-");
this.executor.setThreadFactory(threadFactory);
this.refreshRuntimeModifiableExecutorProperties();
}
this.executor.afterPropertiesSet();
}
private void refreshRuntimeModifiableExecutorProperties() {
int coreSize = this.concurrencyPolicy.getCoreSize();
int maxSize = this.concurrencyPolicy.getMaxSize();
int keepAlive = this.concurrencyPolicy.getKeepAliveSeconds();
if (this.executor.getCorePoolSize() != coreSize) {
this.executor.setCorePoolSize(coreSize);
}
if (this.executor.getMaxPoolSize() != maxSize) {
this.executor.setMaxPoolSize(maxSize);
}
if (this.executor.getKeepAliveSeconds() != keepAlive) {
this.executor.setKeepAliveSeconds(keepAlive);
}
}
public boolean isRunning() {
return this.running;
}
public void start() {
synchronized (this.lifecycleMonitor) {
if (!this.running) {
this.afterPropertiesSet();
}
this.running = true;
}
}
public void stop() {
synchronized (this.lifecycleMonitor) {
if (this.isRunning()) {
this.executor.shutdown();
}
this.running = false;
}
public void destroy() {
this.executor.shutdown();
}
public Message<?> handle(Message<?> message) {
if (!this.isRunning()) {
if (this.executor.isShutdown()) {
throw new MessageHandlerNotRunningException();
}
try {