8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * Copyright (c) 2005 Sun Microsystems Inc. All Rights Reserved
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * The contents of this file are subject to the terms
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * of the Common Development and Distribution License
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * (the License). You may not use this file except in
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * compliance with the License.
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * You can obtain a copy of the License at
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * https://opensso.dev.java.net/public/CDDLv1.0.html or
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * See the License for the specific language governing
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * permission and limitations under the License.
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * When distributing Covered Code, include this CDDL
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * Header Notice in each file and include the License file
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * If applicable, add the following below the CDDL Header,
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * with the fields enclosed by brackets [] replaced by
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * your own identifying information:
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * "Portions Copyrighted [year] [name of copyright owner]"
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * $Id: ThreadPool.java,v 1.10 2008/10/04 00:11:46 arviranga Exp $
5ac19d529aefc79504464993970692f150c44166Craig McDonnell * Portions Copyrighted 2015 ForgeRock AS.
aa3a2aee90d1c61946a08c839d9838be7658b453Craig McDonnellimport org.forgerock.openam.audit.context.AuditRequestContextPropagatingRunnable;
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * This thread pool maintains a number of threads that run the tasks from a task
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * queue one by one. The tasks are handled in asynchronous mode, which means it
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * will not block the main thread to proceed while the task is being processed
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * by the thread pool.
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * This thread pool has a fixed size of threads. It maintains all the tasks to
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * be executed in a task queue. Each thread then in turn gets a task from the
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * queue to execute. If the tasks in the task queue reaches a certain number(the
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * threshold value), it will log an error message and ignore the new incoming
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * tasks until the number of un-executed tasks is less than the threshold value.
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * This guarantees the thread pool will not use up the system resources under
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * heavy load.
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * @supported.all.api
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * Constructs a thread pool with given parameters.
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * @param name
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * name of the thread pool.
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * @param poolSize
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * the thread pool size, indicates how many threads are created
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * in the pool.
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * @param threshold
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * the maximum size of the task queue in the thread pool.
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * @param daemon
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * set the threads as daemon if true; otherwise if not.
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * @param debug
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * Debug object to send debugging message to.
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster public ThreadPool(String name, int poolSize, int threshold, boolean daemon,
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster // initialize the size of the ArrayList, it doesn't need to expand
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster // during runtime.
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster this.taskList = new java.util.ArrayList(threshold);
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster debug.message("Initiating login thread pool size = "
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster + this.poolSize + "\nThreshold = " + threshold);
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster synchronized (this) {
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * Create thread for the pool.
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * @param threadsToCreate number of threads of the pool after creation
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster protected void createThreads(int threadsToCreate) {
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster for (int i = currentThreadCount; i < threadsToCreate; i++) {
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster threads[i - busyThreadCount] = new WorkerThread(poolName, this);
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster threads[i - busyThreadCount].setDaemon(daemon);
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster synchronized (this) {
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster // get threads from the end of the array
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster t = threads[currentThreadCount - busyThreadCount - 1];
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster threads[currentThreadCount - busyThreadCount - 1] = null;
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * Runs a user defined task.
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * @param task
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * user defined task.
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * @throws ThreadPoolException
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster public final void run(Runnable task) throws ThreadPoolException
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster synchronized (this) {
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster // No more tasks will be accepted
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster " thread pool's being shutdown.");
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster if ((threshold > 0) && (taskList.size() >= threshold)) {
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster " thread pool's task queue is full.");
5ac19d529aefc79504464993970692f150c44166Craig McDonnell return new AuditRequestContextPropagatingRunnable(delegate);
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster protected synchronized void deductCurrentThreadCount(){
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster if (shutdownThePool && (busyThreadCount == 0)) {
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster // return the thread to the thread pool
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster protected synchronized void returnThread(WorkerThread t) {
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster // notify the thread pool when all threads are backed
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster // need to discuss whether the thread pool need to wait until
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster // all threads are terminated. For stand alone application, the
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster // answer is yes, however, our application is run under web
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster // container. The reason why we need shutdown because it has a
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster // parameter daemon in the constructor, if it is set to false,
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster // the old implementation has no way to stop the running
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster // threads. For the new implementation, if daemon is set to
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster // false, it is necessary to call shutdown. If daemon is set to
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster // true, it is nice to call it because the thread pool has
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster // better knownledge than the web container to stop the threads
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster // in the pool.
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster // return threads from the end of array
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster threads[currentThreadCount - busyThreadCount - 1] = t;
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster // terminate all the threads since the pass-in parameter of daemon may be
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster // If daemon thread, discard the remaining tasks
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster // else, wait for all tasks to be completed
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster // wait if there are tasks & threads to be executed
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster debug.error("ThreadPool.shutdown Excetion while " +
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster for(int i = 0; i < currentThreadCount - busyThreadCount; i++) {
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster // terminate the thread from the beginning of the array
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster // wait if there are threads running, it will be notified
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster // when they all back.
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster // for test only
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster public synchronized int getCurrentThreadCount() {
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * Returns the size of the task list.
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster // private thread class that fetches tasks from the task queue and
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster // executes them.
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster public WorkerThread(String name, ThreadPool pool) {
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * Starts the thread pool.
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster boolean localShouldTerminate = false;
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster while (true) {
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster synchronized (this) {
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster // need a local copy because they may be changed after
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster // leaving synchronized block.
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster // we may need to log something here!
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster // decide what to log here
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster // don't need to rethrow
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster // decide what to log here
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster // rethrow Error here
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster throw new Error(e);
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster // the thread may has returned already if shutdown is
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster // we may need to log something here!
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster public synchronized void runTask(Runnable toRun) {
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster // Although the thread may not in wait state when this function
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster // is called (the taskList is not empty), it doesn't hurt to
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster // call it. getState method can check whether the Thread is
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster // waiting, but it is available in jdk1.5 or newer.
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster // terminate the thread pool when daemon is set to false
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster // it is better to have a way to terminate the thread pool