/* *************************************************************************************** * Copyright (C) 2006 EsperTech, Inc. All rights reserved. * * http://www.espertech.com/esper * * http://www.espertech.com * * ---------------------------------------------------------------------------------- * * The software in this package is published under the terms of the GPL license * * a copy of which has been included with this distribution in the license.txt file. * *************************************************************************************** */ package com.espertech.esper.core.thread; import com.espertech.esper.client.ConfigurationEngineDefaults; import com.espertech.esper.core.service.EPRuntimeImpl; import com.espertech.esper.core.service.EPServicesContext; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import java.util.concurrent.*; /** * Implementation for engine-level threading. */ public class ThreadingServiceImpl implements ThreadingService { private static final Logger log = LoggerFactory.getLogger(ThreadingServiceImpl.class); private final ConfigurationEngineDefaults.Threading config; private final boolean isTimerThreading; private final boolean isInboundThreading; private final boolean isRouteThreading; private final boolean isOutboundThreading; private BlockingQueue<Runnable> timerQueue; private BlockingQueue<Runnable> inboundQueue; private BlockingQueue<Runnable> routeQueue; private BlockingQueue<Runnable> outboundQueue; private ThreadPoolExecutor timerThreadPool; private ThreadPoolExecutor inboundThreadPool; private ThreadPoolExecutor routeThreadPool; private ThreadPoolExecutor outboundThreadPool; /** * Ctor. * * @param threadingConfig configuration */ public ThreadingServiceImpl(ConfigurationEngineDefaults.Threading threadingConfig) { this.config = threadingConfig; if (ThreadingOption.isThreadingEnabled()) { isTimerThreading = threadingConfig.isThreadPoolTimerExec(); isInboundThreading = threadingConfig.isThreadPoolInbound(); isRouteThreading = threadingConfig.isThreadPoolRouteExec(); isOutboundThreading = threadingConfig.isThreadPoolOutbound(); } else { isTimerThreading = false; isInboundThreading = false; isRouteThreading = false; isOutboundThreading = false; } } public boolean isRouteThreading() { return isRouteThreading; } public boolean isInboundThreading() { return isInboundThreading; } public boolean isTimerThreading() { return isTimerThreading; } public boolean isOutboundThreading() { return isOutboundThreading; } public void initThreading(EPServicesContext services, EPRuntimeImpl runtime) { if (isInboundThreading) { inboundQueue = makeQueue(config.getThreadPoolInboundCapacity()); inboundThreadPool = getThreadPool(services.getEngineURI(), "Inbound", inboundQueue, config.getThreadPoolInboundNumThreads()); } if (isTimerThreading) { timerQueue = makeQueue(config.getThreadPoolTimerExecCapacity()); timerThreadPool = getThreadPool(services.getEngineURI(), "TimerExec", timerQueue, config.getThreadPoolTimerExecNumThreads()); } if (isRouteThreading) { routeQueue = makeQueue(config.getThreadPoolRouteExecCapacity()); routeThreadPool = getThreadPool(services.getEngineURI(), "RouteExec", routeQueue, config.getThreadPoolRouteExecNumThreads()); } if (isOutboundThreading) { outboundQueue = makeQueue(config.getThreadPoolOutboundCapacity()); outboundThreadPool = getThreadPool(services.getEngineURI(), "Outbound", outboundQueue, config.getThreadPoolOutboundNumThreads()); } } private BlockingQueue<Runnable> makeQueue(Integer threadPoolTimerExecCapacity) { if ((threadPoolTimerExecCapacity == null) || (threadPoolTimerExecCapacity <= 0) || (threadPoolTimerExecCapacity == Integer.MAX_VALUE)) { return new LinkedBlockingQueue<Runnable>(); } else { return new ArrayBlockingQueue<Runnable>(threadPoolTimerExecCapacity); } } public void submitRoute(RouteUnitRunnable unit) { try { routeQueue.put(unit); } catch (InterruptedException e) { log.info("Submit interrupted:" + e); } } public void submitInbound(InboundUnitRunnable unit) { try { inboundQueue.put(unit); } catch (InterruptedException e) { log.info("Submit interrupted:" + e); } } public void submitOutbound(OutboundUnitRunnable unit) { try { outboundQueue.put(unit); } catch (InterruptedException e) { log.info("Submit interrupted:" + e); } } public void submitTimerWork(TimerUnit unit) { try { timerQueue.put(unit); } catch (InterruptedException e) { log.info("Submit interrupted:" + e); } } public BlockingQueue<Runnable> getOutboundQueue() { return outboundQueue; } public ThreadPoolExecutor getOutboundThreadPool() { return outboundThreadPool; } public BlockingQueue<Runnable> getRouteQueue() { return routeQueue; } public ThreadPoolExecutor getRouteThreadPool() { return routeThreadPool; } public BlockingQueue<Runnable> getTimerQueue() { return timerQueue; } public ThreadPoolExecutor getTimerThreadPool() { return timerThreadPool; } public BlockingQueue<Runnable> getInboundQueue() { return inboundQueue; } public ThreadPoolExecutor getInboundThreadPool() { return inboundThreadPool; } public synchronized void destroy() { if (timerThreadPool != null) { stopPool(timerThreadPool, timerQueue, "TimerExec"); } if (routeThreadPool != null) { stopPool(routeThreadPool, routeQueue, "RouteExec"); } if (outboundThreadPool != null) { stopPool(outboundThreadPool, outboundQueue, "Outbound"); } if (inboundThreadPool != null) { stopPool(inboundThreadPool, inboundQueue, "Inbound"); } timerThreadPool = null; routeThreadPool = null; outboundThreadPool = null; inboundThreadPool = null; } private ThreadPoolExecutor getThreadPool(String engineURI, String name, BlockingQueue<Runnable> queue, int numThreads) { if (log.isInfoEnabled()) { log.info("Starting pool " + name + " with " + numThreads + " threads"); } if (engineURI == null) { engineURI = "default"; } String threadGroupName = "com.espertech.esper." + engineURI + "-" + name; ThreadGroup threadGroup = new ThreadGroup(threadGroupName); ThreadPoolExecutor pool = new ThreadPoolExecutor(numThreads, numThreads, 1, TimeUnit.SECONDS, queue, new EngineThreadFactory(engineURI, name, threadGroup, Thread.NORM_PRIORITY)); pool.prestartAllCoreThreads(); return pool; } public Thread makeEventSourceThread(String engineURI, String sourceName, Runnable runnable) { if (engineURI == null) { engineURI = "default"; } String threadGroupName = "com.espertech.esper." + engineURI + "-source-" + sourceName; ThreadGroup threadGroup = new ThreadGroup(threadGroupName); return new Thread(threadGroup, runnable); } private void stopPool(ThreadPoolExecutor threadPool, BlockingQueue<Runnable> queue, String name) { if (log.isInfoEnabled()) { log.info("Shutting down pool " + name); } queue.clear(); threadPool.shutdown(); try { threadPool.awaitTermination(10, TimeUnit.SECONDS); } catch (InterruptedException e) { log.error("Interruped awaiting termination", e); } } }