All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.apache.xmlrpc.util.ThreadPool Maven / Gradle / Ivy

/*
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance
 * with the License.  You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied.  See the License for the
 * specific language governing permissions and limitations
 * under the License.    
 */
package org.apache.xmlrpc.util;

import java.util.ArrayList;
import java.util.List;


/** Simple thread pool. A task is executed by obtaining a thread from
 * the pool
 */
public class ThreadPool {
	/** The thread pool contains instances of {@link ThreadPool.Task}.
	 */
	public interface Task {
		/** Performs the task.
		 * @throws Throwable The task failed, and the worker thread won't be used again.
		 */
		void run() throws Throwable;
	}

    /** A task, which may be interrupted, if the pool is shutting down. 
     */
    public interface InterruptableTask extends Task {
        /** Interrupts the task.
         * @throws Throwable Shutting down the task failed.
         */
        void shutdown() throws Throwable;
    }

    private class Poolable {
        private boolean shuttingDown;
        private Task task;
        private Thread thread;
        Poolable(ThreadGroup pGroup, int pNum) {
            thread = new Thread(pGroup, pGroup.getName() + "-" + pNum){
                public void run() {
                    while (!isShuttingDown()) {
                        final Task t = getTask();
                        if (t == null) {
                            try {
                                synchronized (this) {
                                    wait();
                                }
                            } catch (InterruptedException e) {
                                // Do nothing
                            }
                        } else {
                            try {
                                t.run();
                                resetTask();
                                repool(Poolable.this);
                            } catch (Throwable e) {
                                discard(Poolable.this);
                                resetTask();
                            }
                        }
                    }
                }
            };
            thread.start();
        }
        synchronized void shutdown() {
            shuttingDown = true;
            final Task t = getTask();
            if (t != null  &&  t instanceof InterruptableTask) {
                try {
                    ((InterruptableTask) t).shutdown();
                } catch (Throwable th) {
                    // Ignore me
                }
            }
            task = null;
            synchronized (thread) {
                thread.notify();
            }
        }
        private synchronized boolean isShuttingDown() { return shuttingDown; }
        String getName() { return thread.getName(); }
        private synchronized Task getTask() {
            return task;
        }
        private synchronized void resetTask() {
            task = null;
        }
        synchronized void start(Task pTask) {
            task = pTask;
            synchronized (thread) {
                thread.notify();
            }
        }
    }

	private final ThreadGroup threadGroup;
	private final int maxSize;
	private final List waitingThreads = new ArrayList();
	private final List runningThreads = new ArrayList();
	private final List waitingTasks = new ArrayList();
	private int num;


	/** Creates a new instance.
	 * @param pMaxSize Maximum number of concurrent threads.
	 * @param pName Thread group name.
	 */
	public ThreadPool(int pMaxSize, String pName) {
		maxSize = pMaxSize;
		threadGroup = new ThreadGroup(pName);
	}

	synchronized void discard(Poolable pPoolable) {
		pPoolable.shutdown();
        runningThreads.remove(pPoolable);
        waitingThreads.remove(pPoolable);
	}

	synchronized void repool(Poolable pPoolable) {
        if (runningThreads.remove(pPoolable)) {
            if (maxSize != 0  &&  runningThreads.size() + waitingThreads.size() >= maxSize) {
                discard(pPoolable);
            } else {
                waitingThreads.add(pPoolable);
                if (waitingTasks.size() > 0) {
                    Task task = (Task) waitingTasks.remove(waitingTasks.size() - 1);
                    startTask(task);
                }
            }
        } else {
            discard(pPoolable);
        }
	}

	/** Starts a task immediately.
	 * @param pTask The task being started.
	 * @return True, if the task could be started immediately. False, if
	 * the maxmimum number of concurrent tasks was exceeded. If so, you
	 * might consider to use the {@link #addTask(ThreadPool.Task)} method instead.
	 */
	public synchronized boolean startTask(Task pTask) {
		if (maxSize != 0  &&  runningThreads.size() > maxSize) {
			return false;
		}
        Poolable poolable;
		if (waitingThreads.size() > 0) {
		    poolable = (Poolable) waitingThreads.remove(waitingThreads.size()-1);
		} else {
            poolable = new Poolable(threadGroup, num++);
		}
		runningThreads.add(poolable);
        poolable.start(pTask);
		return true;
	}

	/** Adds a task for immediate or deferred execution.
	 * @param pTask The task being added.
	 * @return True, if the task was started immediately. False, if
	 * the task will be executed later.
	 */
	public synchronized boolean addTask(Task pTask) {
		if (startTask(pTask)) {
			return true;
		}
		waitingTasks.add(pTask);
		return false;
	}

	/** Closes the pool.
	 */
	public synchronized void shutdown() {
        while (!waitingThreads.isEmpty()) {
            Poolable poolable = (Poolable) waitingThreads.remove(waitingThreads.size()-1);
            poolable.shutdown();
        }
        while (!runningThreads.isEmpty()) {
            Poolable poolable = (Poolable) runningThreads.remove(runningThreads.size()-1);
            poolable.shutdown();
        }
	}

	/** Returns the maximum number of concurrent threads.
	 * @return Maximum number of threads.
	 */
	public int getMaxThreads() { return maxSize; }

	/** Returns the number of threads, which have actually been created,
     * as opposed to the number of currently running threads.
	 */
    public synchronized int getNumThreads() { return num; }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy