com.arjuna.services.framework.task.TaskManager Maven / Gradle / Ivy
/*
* JBoss, Home of Professional Open Source
* Copyright 2006, Red Hat Middleware LLC, and individual contributors
* as indicated by the @author tags.
* See the copyright.txt in the distribution for a full listing
* of individual contributors.
* This copyrighted material is made available to anyone wishing to use,
* modify, copy, or redistribute it subject to the terms and conditions
* of the GNU Lesser General Public License, v. 2.1.
* This program is distributed in the hope that it will be useful, but WITHOUT A
* 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,
* v.2.1 along with this distribution; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
* MA 02110-1301, USA.
*
* (C) 2005-2006,
* @author JBoss Inc.
*/
package com.arjuna.services.framework.task ;
import java.util.HashSet;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.Set;
import com.arjuna.webservices.logging.WSCLogger;
/**
* This class manages the client side of the task manager
*
* @author kevin
*/
public class TaskManager
{
/**
* The singleton.
*/
private static final TaskManager MANAGER = new TaskManager() ;
/**
* The default maximum worker count.
*/
private static final int DEFAULT_MAXIMUM_THREAD_COUNT = 10 ;
/**
* The default minimum worker count.
*/
private static final int DEFAULT_MINIMUM_THREAD_COUNT = 0 ;
/**
* The minimum worker pool count.
*/
private int minimumWorkerCount = DEFAULT_MINIMUM_THREAD_COUNT ;
/**
* The maximum worker pool count.
*/
private int maximumWorkerCount = DEFAULT_MAXIMUM_THREAD_COUNT ;
/**
* The set of already allocated workers.
*/
private Set workerPool = new HashSet() ;
/**
* The current list of tasks.
*/
private LinkedList taskList = new LinkedList() ;
/**
* The counter used for naming the threads.
*/
private int taskCount ;
/**
* The number of worker waiting.
*/
private int waitingCount ;
/**
* A flag indicating that shutdown is in progress.
*/
private boolean shutdown ;
/**
* Get the singleton controlling the tasks.
*
* @return The task manager.
*/
public static TaskManager getManager()
{
return MANAGER ;
}
/**
* Private to prevent initialisation.
*/
private TaskManager()
{
}
/**
* Queue the task for execution.
*
* @param task The task to be executed.
* @return true if the task was queued, false otherwise.
*
*/
public boolean queueTask(final Task task)
{
final boolean debugEnabled = WSCLogger.logger.isTraceEnabled() ;
synchronized(workerPool)
{
if (shutdown)
{
if (debugEnabled)
{
WSCLogger.logger.tracev("Shutdown in progress, ignoring task") ;
}
return false ;
}
}
final boolean notify ;
synchronized(taskList)
{
taskList.addLast(task) ;
notify = (waitingCount > 0) ;
if (notify)
{
if (debugEnabled)
{
WSCLogger.logger.tracev("queueTask: notifying waiting workers ({0})",
new Object[] {new Integer(waitingCount)}) ;
}
taskList.notify() ;
}
}
final boolean create ;
synchronized(workerPool)
{
create = ((workerPool.size() < minimumWorkerCount) ||
((workerPool.size() < maximumWorkerCount) && !notify)) ;
}
if (create)
{
if (debugEnabled)
{
WSCLogger.logger.tracev("queueTask: creating worker") ;
}
createWorker() ;
}
else if (debugEnabled)
{
WSCLogger.logger.tracev("queueTask: queueing task for execution") ;
}
return true ;
}
/**
* Set the minimum worker count for the pool.
*
* @param minimumWorkerCount The minimum worker count.
*
*/
public void setMinimumWorkerCount(final int minimumWorkerCount)
{
final boolean debugEnabled = WSCLogger.logger.isTraceEnabled() ;
synchronized(workerPool)
{
if (shutdown)
{
if (debugEnabled)
{
WSCLogger.logger.tracev("shutdown in progress, ignoring set minimum worker count") ;
}
return ;
}
this.minimumWorkerCount = (minimumWorkerCount < 0 ? DEFAULT_MINIMUM_THREAD_COUNT
: minimumWorkerCount) ;
if (this.minimumWorkerCount > maximumWorkerCount)
{
maximumWorkerCount = this.minimumWorkerCount ;
}
if (debugEnabled)
{
WSCLogger.logger.tracev("setMinimumWorkerCount: {0}") ;
}
}
while(true)
{
final boolean create ;
synchronized(workerPool)
{
create = (workerPool.size() < this.minimumWorkerCount) ;
}
if (create)
{
createWorker() ;
}
else
{
break ;
}
}
}
/**
* Get the minimum worker count for the pool.
*
* @return The minimum worker count.
*/
public int getMinimumWorkerCount()
{
synchronized(workerPool)
{
return minimumWorkerCount ;
}
}
/**
* Set the maximum worker count for the pool.
*
* @param maximumWorkerCount The maximum worker count.
*/
public void setMaximumWorkerCount(final int maximumWorkerCount)
{
final boolean debugEnabled = WSCLogger.logger.isTraceEnabled() ;
synchronized(workerPool)
{
if (shutdown)
{
if (debugEnabled)
{
WSCLogger.logger.tracev("shutdown in progress, ignoring set maximum worker count") ;
}
return ;
}
this.maximumWorkerCount = (maximumWorkerCount < 0 ? DEFAULT_MAXIMUM_THREAD_COUNT
: maximumWorkerCount) ;
if (minimumWorkerCount > this.maximumWorkerCount)
{
minimumWorkerCount = this.maximumWorkerCount ;
}
if (debugEnabled)
{
WSCLogger.logger.tracev("setMaximumWorkerCount: {0}",
new Object[] {new Integer(this.maximumWorkerCount)}) ;
}
synchronized(taskList)
{
if ((workerPool.size() > this.maximumWorkerCount)
&& (waitingCount > 0))
{
if (debugEnabled)
{
WSCLogger.logger.tracev("setMaximumWorkerCount: reducing pool size from {0} to {1}",
new Object[] {new Integer(workerPool.size()), new Integer(this.maximumWorkerCount)}) ;
}
taskList.notify() ;
}
}
}
}
/**
* Get the maximum worker count for the pool.
*
* @return The maximum worker count.
*/
public int getMaximumWorkerCount()
{
synchronized(workerPool)
{
return maximumWorkerCount ;
}
}
/**
* Get the current worker count for the pool.
*
* @return The current worker count.
*/
public int getWorkerCount()
{
synchronized(workerPool)
{
return workerPool.size() ;
}
}
/**
* Close all threads and reset the task list. This method waits until all
* threads have finished before returning.
*/
public void shutdown()
{
final boolean debugEnabled = WSCLogger.logger.isTraceEnabled() ;
synchronized(workerPool)
{
if (shutdown)
{
if (debugEnabled)
{
WSCLogger.logger.tracev("Shutdown already in progress") ;
}
}
else
{
setMaximumWorkerCount(0) ;
shutdown = true ;
}
}
while(true)
{
final Thread waitThread ;
synchronized(workerPool)
{
final Iterator workerPoolIter = workerPool.iterator() ;
if (workerPoolIter.hasNext())
{
waitThread = (Thread) workerPoolIter.next() ;
}
else
{
waitThread = null ;
}
}
if (waitThread == null)
{
break ;
}
else
{
try
{
waitThread.join() ;
}
catch (final InterruptedException ie)
{
} // Ignore
}
}
synchronized(workerPool)
{
if (shutdown)
{
taskList.clear() ;
shutdown = false ;
}
}
}
/**
* Get another task from the pool.
*
* @return The next task from the pool or null if finished.
*
*/
Task getTask()
{
final boolean debugEnabled = WSCLogger.logger.isTraceEnabled() ;
while(true)
{
final boolean remove ;
synchronized(workerPool)
{
final int excessCount = workerPool.size() - maximumWorkerCount ;
if (excessCount > 0)
{
if (debugEnabled)
{
WSCLogger.logger.tracev("getTask: releasing thread") ;
}
synchronized(taskList)
{
if ((excessCount > 1) && (waitingCount > 0))
{
if (debugEnabled)
{
WSCLogger.logger.tracev("getTask: notifying waiting thread about excess count {0}",
new Object[] {new Integer(excessCount)}) ;
}
taskList.notify() ;
}
}
remove = true ;
}
else
{
remove = false ;
}
}
if (remove)
{
final Thread currentThread = Thread.currentThread() ;
synchronized(workerPool)
{
workerPool.remove(currentThread) ;
}
return null ;
}
synchronized(taskList)
{
final int numTasks = taskList.size() ;
if (numTasks > 0)
{
final Task task = (Task) taskList.removeFirst() ;
if ((numTasks > 1) && (waitingCount > 0))
{
taskList.notify() ;
}
if (debugEnabled)
{
WSCLogger.logger.tracev("getTask: returning task") ;
}
return task ;
}
waitingCount++ ;
if (debugEnabled)
{
WSCLogger.logger.tracev("getTask: waiting for task") ;
}
try
{
taskList.wait() ;
}
catch (final InterruptedException ie)
{
if (debugEnabled)
{
WSCLogger.logger.tracev("getTask: interrupted") ;
}
}
finally
{
waitingCount-- ;
}
}
}
}
/**
* Create and register a task worker.
*/
private void createWorker()
{
final TaskWorker taskWorker = new TaskWorker(this) ;
final String name ;
synchronized(workerPool)
{
name = "TaskWorker-" + ++taskCount ;
}
final Thread thread = new Thread(taskWorker, name) ;
thread.setDaemon(true) ;
synchronized(workerPool)
{
workerPool.add(thread) ;
}
thread.start() ;
}
}