/* * Copyright (c) 2008 Stiftung Deutsches Elektronen-Synchrotron, * Member of the Helmholtz Association, (DESY), HAMBURG, GERMANY. * * THIS SOFTWARE IS PROVIDED UNDER THIS LICENSE ON AN "../AS IS" BASIS. * WITHOUT WARRANTY OF ANY KIND, EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED * TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR PARTICULAR PURPOSE AND * NON-INFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE * FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR * THE USE OR OTHER DEALINGS IN THE SOFTWARE. SHOULD THE SOFTWARE PROVE DEFECTIVE * IN ANY RESPECT, THE USER ASSUMES THE COST OF ANY NECESSARY SERVICING, REPAIR OR * CORRECTION. THIS DISCLAIMER OF WARRANTY CONSTITUTES AN ESSENTIAL PART OF THIS LICENSE. * NO USE OF ANY SOFTWARE IS AUTHORIZED HEREUNDER EXCEPT UNDER THIS DISCLAIMER. * DESY HAS NO OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, * OR MODIFICATIONS. * THE FULL LICENSE SPECIFYING FOR THE SOFTWARE THE REDISTRIBUTION, MODIFICATION, * USAGE AND OTHER RIGHTS AND OBLIGATIONS IS INCLUDED WITH THE DISTRIBUTION OF THIS * PROJECT IN THE FILE LICENSE.HTML. IF THE LICENSE IS NOT INCLUDED YOU MAY FIND A COPY * AT HTTP://WWW.DESY.DE/LEGAL/LICENSE.HTM */ package org.csstudio.platform; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.concurrent.LinkedBlockingQueue; import java.util.concurrent.ScheduledExecutorService; import java.util.concurrent.ThreadFactory; import java.util.concurrent.ThreadPoolExecutor; import java.util.concurrent.TimeUnit; import java.util.concurrent.atomic.AtomicInteger; import org.slf4j.Logger; import org.slf4j.LoggerFactory; /** * Service for the execution of asynchronous tasks using thread pools. * * @author swende * */ public class ExecutionService { private static final Logger LOG = LoggerFactory.getLogger(ExecutionService.class); private static ExecutionService _instance; private static final int HIGH_PRIORITY_THREADS = 20; private static final int NORMAL_PRIORITY_THREADS = 20; private static final int LOW_PRIORITY_THREADS = 20; private static final int SCHEDULED_THREADS = 3; private static LinkedBlockingQueue<Runnable> _lowPriorityQueue; private static LinkedBlockingQueue<Runnable> _normalPriorityQueue; private static LinkedBlockingQueue<Runnable> _highPriorityQueue; private ScheduledExecutorService _scheduledExecutorService; private ExecutorService _lowPriorityExectorService; private ExecutorService _normalPriorityExectorService; private ExecutorService _highPriorityExecutorService; private ExecutionService() { _lowPriorityQueue = new LinkedBlockingQueue<Runnable>(); _normalPriorityQueue = new LinkedBlockingQueue<Runnable>(); _highPriorityQueue = new LinkedBlockingQueue<Runnable>(); _lowPriorityExectorService = new ThreadPoolExecutor(LOW_PRIORITY_THREADS, LOW_PRIORITY_THREADS, 0L, TimeUnit.MILLISECONDS, _lowPriorityQueue, new CssThreadFactory(Thread.MIN_PRIORITY)); _normalPriorityExectorService = new ThreadPoolExecutor(NORMAL_PRIORITY_THREADS, NORMAL_PRIORITY_THREADS, 0L, TimeUnit.MILLISECONDS, _normalPriorityQueue, new CssThreadFactory(Thread.NORM_PRIORITY)); _highPriorityExecutorService = new ThreadPoolExecutor(HIGH_PRIORITY_THREADS, HIGH_PRIORITY_THREADS, 0L, TimeUnit.MILLISECONDS, _highPriorityQueue, new CssThreadFactory(Thread.MAX_PRIORITY)); _scheduledExecutorService = Executors.newScheduledThreadPool(SCHEDULED_THREADS); } /** * Returns the singleton instance. * * @return the singleton instance */ public static synchronized ExecutionService getInstance() { if (_instance == null) { _instance = new ExecutionService(); } return _instance; } /** * Executes the specified runnable with high priority. * * @param runnable * the runnable */ public void executeWithHighPriority(final Runnable runnable) { doRun(_highPriorityExecutorService, runnable); } /** * Executes the specified runnable with normal priority. * * @param runnable * the runnable */ public void executeWithNormalPriority(final Runnable runnable) { doRun(_normalPriorityExectorService, runnable); } /** * Returns the number of runnables waiting for execution with high priority. */ public int getHighPriorityQueueSize() { return _highPriorityQueue.size(); } /** * Returns the number of runnables waiting for execution with normal priority. */ public int getNormalPriorityQueueSize() { return _normalPriorityQueue.size(); } /** * Returns the number of runnables waiting for execution with low priority. */ public int getLowPriorityQueueSize() { return _lowPriorityQueue.size(); } /** * Executes the specified runnable with normal priority. * * @param runnable * the runnable */ public void executeWithLowPriority(final Runnable runnable) { doRun(_lowPriorityExectorService, runnable); } private void doRun(ExecutorService service, final Runnable runnable) { service.execute(new Runnable() { @Override public void run() { try { runnable.run(); } catch (Throwable t) { LOG.error(t.toString()); } } }); } public ScheduledExecutorService getScheduledExecutorService() { return _scheduledExecutorService; } private static class CssThreadFactory implements ThreadFactory { static final AtomicInteger poolNumber = new AtomicInteger(1); final ThreadGroup group; final AtomicInteger threadNumber = new AtomicInteger(1); final String namePrefix; private int priority = Thread.NORM_PRIORITY; CssThreadFactory(int priority) { this.priority = priority; SecurityManager s = System.getSecurityManager(); group = (s != null) ? s.getThreadGroup() : Thread.currentThread().getThreadGroup(); namePrefix = "css-threadpool-" + poolNumber.getAndIncrement() + "-thread-"; } @Override public Thread newThread(Runnable r) { Thread t = new Thread(group, r, namePrefix + threadNumber.getAndIncrement(), 0); t.setDaemon(false); t.setPriority(priority); return t; } } }