ThreadPoolManager.java :  » Net » Coadunation_1.0.1 » com » rift » coad » lib » thread » pool » Java Open Source

Java Open Source » Net » Coadunation_1.0.1 
Coadunation_1.0.1 » com » rift » coad » lib » thread » pool » ThreadPoolManager.java
/*
 * CoadunationLib: The coadunation libraries.
 * Copyright (C) 2007  Rift IT Contracting
 *
 * 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., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
 *
 * ThreadPoolManager.java
 */

// package path
package com.rift.coad.lib.thread.pool;

// java imports
import java.util.Vector;
import java.util.Iterator;
import java.util.concurrent.atomic.AtomicInteger;
        
// logging import
import org.apache.log4j.Logger;

// coadunation imports
import com.rift.coad.lib.common.ClassUtil;
import com.rift.coad.lib.thread.CoadunationThread;
import com.rift.coad.lib.thread.ThreadStateMonitor;

/**
 * This object is responsible for managing a pool of threads assigned to process
 * a task object.
 *
 * @author Brett Chaldecott
 */
public class ThreadPoolManager {
    
    /**
     * This class is responsible for processing the tasks.
     */
    public class PoolThread extends CoadunationThread {
        
        // The classes private member variables
        private ThreadStateMonitor state = new ThreadStateMonitor();
        private ThreadPoolManager threadPoolManager = null;
        private Class taskClass = null;
        
        /**
         * The constructor of pool thread.
         *
         * @param threadPool The reference to the thread pool.
         * @param taskClass The task object to process.
         * @exception Exception
         */
        public PoolThread(ThreadPoolManager threadPoolManager, Class taskClass) 
                throws Exception {
            this.threadPoolManager = threadPoolManager;
            this.taskClass = taskClass;
        }
        
        
        /**
         * This method replaces the run method in the BasicThread.
         *
         * @exception Exception
         */
        public void process() throws Exception {
            while(!state.isTerminated()) {
                if (!monitor()) {
                    break;
                }
                try {
                    Task task = (Task)taskClass.newInstance();
                    task.process(threadPoolManager);
                } catch (Exception ex) {
                    log.error("Failed to process a task : " + ex.getMessage(),
                            ex);
                }
                processing.decrementAndGet();
            }
            removeThread(this);
            log.debug("Pool thread exiting");
        }


        /**
         * This method will be implemented by child objects to terminate the
         * processing of this thread.
         */
        public void terminate() {
            state.terminate(true);
        }
        
    }
    
    // the logger reference
    protected Logger log =
            Logger.getLogger(ThreadPoolManager.class.getName());
    
    // privat member variables
    private AtomicInteger processing = new AtomicInteger(0);
    private int currentSize = 0;
    private int minSize = 0;
    private int maxSize = 0;
    private Class taskClass = null;
    private String username = null;
    private Vector threadList = new Vector();
    private ThreadStateMonitor state = new ThreadStateMonitor();
    private int releaseThread = 1;
    
    /** 
     * Creates a new instance of ThreadPoolManager 
     *
     * @param size The size of this thread pool.
     * @param taskClass The class that implements the task interface.
     * @param username The name of the user that the threads will run as.
     * @exception PoolException
     */
    public ThreadPoolManager(int size, Class taskClass, String username) throws
            PoolException {
        validateTask(taskClass);
        this.minSize = size;
        this.maxSize = size;
        this.taskClass = taskClass;
        this.username = username;
        startThreads(minSize);
    }
    
    
    /** 
     * Creates a new instance of ThreadPoolManager 
     *
     * @param minSize The minimum size of this thread pool.
     * @param maxSize The maximum size of this thread pool.
     * @param taskClass The class that implements the task interface.
     * @param username The name of the user that the threads will run as.
     * @exception PoolException
     */
    public ThreadPoolManager(int minSize, int maxSize, Class taskClass, 
            String username) throws PoolException {
        validateTask(taskClass);
        this.minSize = minSize;
        this.maxSize = maxSize;
        this.taskClass = taskClass;
        this.username = username;
        startThreads(minSize);
    }
    
    
    /**
     * This method returns the min size.
     *
     * @return The minimum size of the thread pool.
     */
    public synchronized int getMinSize() {
        return minSize;
    }
    
    
    /**
     * This method sets the minum size of the thread pool.
     *
     * @param minSize The minimum size of the pool.
     * @exception PoolException
     */
    public synchronized void setMinSize(int minSize) throws PoolException {
        checkState();
        if (minSize > maxSize) {
            throw new PoolException("Min size must be smaller than max size.");
        }
        this.minSize = minSize;
        if (currentSize < minSize) {
            startThreads(minSize - currentSize);
        }
        notifyAll();
    }
    
    
    /**
     * This method returns the max size of the thread pool.
     *
     * @return The maximum size of the thread pool.
     */
    public synchronized int getMaxSize() {
        return maxSize;
    }
    
    
    /**
     * This method sets the maximum size of the thread pool.
     *
     * @param maxSize The maximum size of the thread pool.
     */
    public synchronized void setMaxSize(int maxSize) throws PoolException{
        checkState();
        if (maxSize < minSize) {
            throw new PoolException("Max size must be greater than min size.");
        }
        this.maxSize = maxSize;
        notifyAll();
    }
    
    
    /**
     * This method returns the size of the thread pool.
     *
     * @return The size of the thread pool.
     */
    public synchronized int getSize() {
        return maxSize;
    }
    
    
    /**
     * This method sets the size of the thread pool.
     *
     * @param size The size of the thread pool.
     * @exception PoolException
     */
    public synchronized void setSize(int size) throws PoolException {
        checkState();
        this.minSize = size;
        this.maxSize = size;
        if (currentSize < size) {
            startThreads(size - currentSize);
        }
        notifyAll();
    }
    
    
    /**
     * This method releases threads a thread from the pool.
     *
     * @exception PoolException
     */
    public synchronized void releaseThread() throws PoolException {
        int processing = this.processing.get();
        this.releaseThread++;
        processing += releaseThread;
        if (processing > minSize && processing <= maxSize) {
            startThreads(1);
        }
        notify();
    }
    
    
    /**
     * This method is called to terminate the thread pool.
     */
    public void terminate() throws PoolException {
        state.terminate(true);
        Vector threadListCopy = null;
        synchronized(this) {
            threadListCopy = new Vector(threadList);
        }
        for (Iterator iter = threadListCopy.iterator(); iter.hasNext();) {
            CoadunationThread thread = (CoadunationThread)iter.next();
            thread.terminate();
        }
        
        synchronized(this) {
            notifyAll();
        }
    }
    
    
    /**
     * This method validates the task object.
     *
     * @param taskClass The class to test.
     * @exception PoolException
     */
    private void validateTask(Class taskClass) throws PoolException {
        if (!ClassUtil.testForParent(taskClass,Task.class)) {
            throw new PoolException("Task class [" + taskClass.getName() + 
                    "] does not inherit from [" + Task.class.getName() + "]");
        }
    }
    
    
    /**
     * This method is called to start the threads
     *
     * @param size The number of threads to release.
     * @exception PoolException
     */
    private void startThreads(int size) throws PoolException {
        try {
            for (int count = 0; count < size; count++) {
                PoolThread thread = new PoolThread(this,taskClass);
                thread.start(username);
                addThread(thread);
            }
        } catch (Exception ex) {
            log.error("Failed to start the threads : " + 
                    ex.getMessage(),ex);
            throw new PoolException("Failed to start the threads : " + 
                    ex.getMessage(),ex);
        }
    }
    
    
    /**
     * This method is call by the pool threads to monitor the processing.
     *
     * @return TRUE if processing, should continue, FALSE if not.
     * @exception PoolException
     */
    private synchronized boolean monitor() throws PoolException {
        while (true) {
            if (currentSize > maxSize) {
                currentSize--;
                return false;
            } else if (releaseThread > 0) {
                releaseThread--;
                processing.incrementAndGet();
                return true;
            } else if (currentSize > minSize) {
                currentSize--;
                return false;
            } else if (state.isTerminated()) {
                currentSize--;
                return false;
            }
            try {
                wait();
            } catch (Exception ex) {
                log.error("Wait failed : " + ex.getMessage());
            }
        }
    }
    
    
    /**
     * This method adds a thread to the list of threads
     */
    private synchronized void addThread(PoolThread thread) {
        currentSize++;
        threadList.add(thread);
    }
    
    
    /**
     * This method is called to remove a thread from the list.
     *
     * @param thread The thread to remove
     */
    private synchronized void removeThread(PoolThread thread) {
        threadList.remove(thread);
    }
    
    
    /**
     * This method is used to check the state of this pool.
     *
     * @exception PoolException
     */
    private void checkState() throws PoolException {
        if (state.isTerminated()) {
            throw new PoolException("The thread pool has been terminated");
        }
    }
}
java2s.com  | Contact Us | Privacy Policy
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.