/*******************************************************************************
* ALMA - Atacama Large Millimiter Array
* (c) European Southern Observatory, 2002
* Copyright by ESO (in the framework of the ALMA collaboration)
* and Cosylab 2002, All rights reserved
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
package alma.ACS.jbaci;
import java.util.concurrent.PriorityBlockingQueue;
import java.util.concurrent.ThreadFactory;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
/**
* BACI dispatcher (thread pool)
* @author <a href="mailto:matej.sekoranjaATcosylab.com">Matej Sekoranja</a>
* @version $id$
*/
public class BACIDispatcher {
/**
* Thread pool.
*/
private ThreadPoolExecutor threadPool;
/**
* Number of threads in thread pool.
*/
private static final int MAX_REQUESTS = 100;
/**
* Number of requests ( in thread pool (guarantees order of execution).
*/
private static final int POOL_THREADS = 10;
/**
* Constructor.
* @param threadFactory thread factory to be used to create thread, if <code>null</code> no factory is being used
*/
public BACIDispatcher(ThreadFactory threadFactory)
{
// TODO make PriorityBlockingQueue bounded!!! (to MAX_REQUESTS)
// TODO use PooledExecutorWithWaitInNewThreadWhenBlocked...
if (threadFactory != null)
threadPool = new ThreadPoolExecutor(POOL_THREADS, POOL_THREADS,
Long.MAX_VALUE, TimeUnit.NANOSECONDS,
new PriorityBlockingQueue<Runnable>(MAX_REQUESTS, new PrioritizedRunnableComparator<Runnable>()), threadFactory);
else
threadPool = new ThreadPoolExecutor(POOL_THREADS, POOL_THREADS,
Long.MAX_VALUE, TimeUnit.NANOSECONDS,
new PriorityBlockingQueue<Runnable>(MAX_REQUESTS, new PrioritizedRunnableComparator<Runnable>()));
threadPool.prestartAllCoreThreads();
}
/**
* Execute action.
* If the maximum pool size or queue size is bounded,
* then it is possible for incoming execute requests to block.
* <code>BACIDispatcher</code> uses its own blocking policy:
* creating a new thread, which will call blocking execute.
* @param action action to execute.
* @return <code>true</code> on success.
*/
public boolean execute(PrioritizedRunnable action)
{
try
{
threadPool.execute(action);
return true;
}
catch (Throwable th)
{
return false;
}
}
/**
* Shutdown dispatcher.
*/
public void shutdown()
{
// initiate shutdown
threadPool.shutdown();
// first be kind and wait up to 3 seconds to terminate
try {
threadPool.awaitTermination(3, TimeUnit.SECONDS);
} catch (InterruptedException e) {
// noop
}
// no more "mister-nice-guy", terminate all
threadPool.shutdownNow();
}
}