8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster/**
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster *
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * Copyright (c) 2007 Sun Microsystems Inc. All Rights Reserved
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster *
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 *
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 * opensso/legal/CDDLv1.0.txt
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * See the License for the specific language governing
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * permission and limitations under the License.
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster *
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * When distributing Covered Code, include this CDDL
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * Header Notice in each file and include the License file
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * at opensso/legal/CDDLv1.0.txt.
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 *
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * $Id: JSSThreadPool.java,v 1.3 2008/06/25 05:41:34 qcheng Exp $
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster *
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster */
8af80418ba1ec431c8027fa9668e5678658d3611Allan Fosterpackage com.iplanet.services.comm.https;
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster
8af80418ba1ec431c8027fa9668e5678658d3611Allan Fosterimport com.sun.identity.shared.debug.Debug;
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster
8af80418ba1ec431c8027fa9668e5678658d3611Allan Fosterpublic class JSSThreadPool {
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster public static final int DEFAULT_THREAD_POOL_SIZE = 20;
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster private static Debug debug;
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster private ReaderWriterClear[] readerWriter;
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster private int poolSize;
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster private String poolName;
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster private java.util.LinkedList taskList;
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster private int busyThreadCount;
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster private int currentThreadCount;
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster private int busyReaderWriterCount;
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster private int currentReaderWriterCount;
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster private boolean shutdownThePool;
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster private boolean daemon;
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster private WorkerThread[] threads;
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster /**
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * Constructs a thread pool with given parameters.
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster *
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 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 */
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster public JSSThreadPool(String name, int poolSize, boolean daemon, Debug debug) {
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster this.debug = debug;
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster this.poolSize = poolSize;
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster this.poolName = name;
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.LinkedList();
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster this.busyThreadCount = 0;
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster this.currentThreadCount = 0;
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster this.busyReaderWriterCount = 0;
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster this.currentReaderWriterCount = 0;
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster this.daemon = daemon;
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster this.shutdownThePool = false;
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster this.threads = new WorkerThread[poolSize];
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster this.readerWriter = new ReaderWriterClear[poolSize];
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster synchronized (this) {
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster createThreads(poolSize);
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster }
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster }
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster /**
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * Create thread for the pool.
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster *
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * @param threadsToCreate number of threads of the pool after creation
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster */
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster protected void createThreads(int threadsToCreate) {
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster if (threadsToCreate > poolSize) {
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster threadsToCreate = poolSize;
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster }
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 threads[i - busyThreadCount].start();
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster }
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster currentThreadCount = threadsToCreate;
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster }
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster private WorkerThread getAvailableThread() {
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster WorkerThread t = null;
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster synchronized (this) {
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster if (currentThreadCount == busyThreadCount) {
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster createThreads(poolSize);
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster }
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 busyThreadCount++;
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster }
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster return t;
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster }
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster /**
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * Runs a user defined task.
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster *
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * @param task
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * user defined task.
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * @throws ThreadPoolException
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster */
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster public void run(Runnable task) {
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster WorkerThread t = null;
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster synchronized (this) {
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster if (busyThreadCount == poolSize) {
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster taskList.addLast(task);
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster }
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster else{
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster t = getAvailableThread();
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster }
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster }
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster if ((t != null) && (task != null)) {
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster t.runTask(task);
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster }
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster }
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster protected synchronized void deductCurrentThreadCount(){
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster currentThreadCount--;
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster busyThreadCount--;
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster if (!taskList.isEmpty()) {
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster WorkerThread t = getAvailableThread();
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster t.runTask((Runnable)taskList.removeFirst());
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster }
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster }
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster // return the thread to the thread pool
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster protected synchronized void returnThread(WorkerThread t) {
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster if(shutdownThePool) {
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster t.terminate();
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster // notify the thread pool when all threads are backed
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster // need to discuss whether the thread pool need to wait until all
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster // threads are terminated. For stand alone application, the answer
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster // is yes, however, our application is run under web container.
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster // The reason why we need shutdown because it has a parameter daemon
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster // in the constructor, if it is set to false, the old implementation
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster // has no way to stop the running threads. For the new
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster // implementation, if daemon is set to false, it is necessary to
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster // call shutdown. If daemon is set to true, it is nice to call it
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster // because the thread pool has better knownledge than the web
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster // container to stop the threads in the pool.
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster t.setNeedReturn(false);
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster busyThreadCount--;
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster if(busyThreadCount == 0){
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster notify();
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster }
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster return;
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster }
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster if (!taskList.isEmpty()){
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster t.runTask((Runnable)taskList.remove(0));
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster }
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster else{
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster busyThreadCount--;
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster // return threads from the end of array
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster threads[currentThreadCount - busyThreadCount - 1] = t;
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster }
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster }
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster // terminate all the threads since the pass-in parameter of daemon may be
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster // false
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster public synchronized void shutdown() {
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster if(!shutdownThePool) {
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster shutdownThePool = true;
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster for(int i = 0; i < currentThreadCount - busyThreadCount; i++) {
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster // terminate the thread from the beginning of the array
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster threads[i].terminate();
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster }
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster while(busyThreadCount != 0){
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster try{
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster // wait if there are threads running, it will be notified
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster // when they all back.
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster wait();
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster } catch (Exception ex) {
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster ex.printStackTrace();
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster }
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster }
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster currentThreadCount = busyThreadCount = 0;
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster threads = null;
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster }
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster }
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster // for test only
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster public synchronized int getCurrentThreadCount() {
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster return currentThreadCount;
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster }
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster /*
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * Returns the size of the task list.
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster */
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster public int getCurrentSize() {
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster return taskList.size();
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster }
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster // private thread class that fetches tasks from the task queue and
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster // executes them.
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster private class WorkerThread extends Thread {
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster private Runnable task = null;
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster private JSSThreadPool pool;
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster private boolean needReturn;
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster private boolean shouldTerminate;
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster public WorkerThread(String name, JSSThreadPool pool) {
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster setName(name);
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster this.pool = pool;
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster this.shouldTerminate = false;
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster this.needReturn = true;
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster }
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster /**
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * Starts the thread pool.
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster */
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster public void run() {
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster boolean localShouldTerminate = false;
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster Runnable localTask = null;
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster WorkerThread t = this;
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster while (true) {
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster try{
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster synchronized (this) {
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster if ((task == null) && (!shouldTerminate)){
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster this.wait();
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster }
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster // need a local copy because they may be changed after
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster // leaving synchronized block.
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster localShouldTerminate = shouldTerminate;
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster localTask = task;
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster task = null;
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster }
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster if (localShouldTerminate) {
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster // we may need to log something here!
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster break;
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster }
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster if(localTask != null){
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster localTask.run();
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster }
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster } catch (RuntimeException ex) {
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster debug.error("Running task " + task, ex);
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster // decide what to log here
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster pool.deductCurrentThreadCount();
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster localShouldTerminate = true;
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster needReturn = false;
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster } catch (Exception ex) {
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster // don't need to rethrow
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster debug.error("Running task " + task, ex);
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster } catch (Throwable e) {
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster debug.error("Running task " + task, e);
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster // decide what to log here
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster pool.deductCurrentThreadCount();
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster localShouldTerminate = true;
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster needReturn = false;
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster // rethrow Error here
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster throw new Error(e);
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster } finally {
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster // the thread may has returned already if shutdown is
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster // called.
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster if (needReturn) {
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster pool.returnThread(t);
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster }
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster }
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster if (localShouldTerminate) {
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster // we may need to log something here!
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster break;
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster }
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster }
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster }
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster public synchronized void runTask(Runnable toRun) {
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster this.task = 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 this.notify();
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster }
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster
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
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster public synchronized void terminate() {
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster shouldTerminate = true;
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster this.notify();
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster }
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster public synchronized void setNeedReturn(boolean value){
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster // this will be set by ThreadPool.returnThread when shutdown is
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster // called.
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster needReturn = value;
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster }
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster }
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster}
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster