core.sample.pool.WorkerThread.java Source code

Java tutorial

Introduction

Here is the source code for core.sample.pool.WorkerThread.java

Source

/*
 * Copyright 2004-2005 the original author.
 * 
 * Licensed 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 core.sample.pool;

import java.lang.reflect.InvocationTargetException;

import org.apache.commons.beanutils.MethodUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

/**
 * @author Murali Kosaraju WorkerThread class - This is the worker thread which
 *         gets pooled for re-use. We should customize this for the desired
 *         behaviour.
 */
public class WorkerThread extends Thread {

    private static Log log = LogFactory.getLog(WorkerThread.class);

    public WorkerThread() {
        //default constructor
    }

    /**
     * Keeps the thread running when false. When set to true, completes the
     * execution of the thread and stops.
     */
    private boolean stopped = false;

    /**
     * Manages the thread's state. When the thread is first created, running is
     * set to false. When the thread is assigned a task for the first time, the
     * thread continues to be in the running state until stopped.
     */
    private boolean running = false;

    /**
     * Manages the thread's internal state with respect to the task. When the
     * thread finishes executing the task, this is set to true.
     */
    private boolean done = true;

    /**
     * The class name where the method to be execute is defined.
     */
    private String className;

    /**
     * The method name to be executed.
     */
    private String methodName;

    /**
     * The parameters to be passed for the method.
     */
    private Object[] methodParams;

    /**
     * The parameter types for the respective parameters..
     */
    private Class[] parmTypes;

    /**
     * The object to synchronize upon for notifying the completion of task.
     */
    private Object syncObject = null;

    /**
     * The result of our execution.
     */
    private Object result = null;

    /**
     * The pool being used. We use this if we need to return the object back to the
     * pool. If this is not set, we assume that the client will take care of returning
     * the object back to the pool.
     */
    private ThreadPool pool = null;

    /**
     * @param pool The pool to set.
     */
    public void setPool(ThreadPool pool) {
        this.pool = pool;
    }

    /**
     * @param result The result to set.
     */
    public void setResult(Object result) {
        this.result = result;
    }

    /**
     * @return Returns the result.
     */
    public Object getResult() {
        return result;
    }

    /**
     * @return Returns the className.
     */
    public String getClassName() {
        return className;
    }

    /**
     * @param className The className to set.
     */
    public void setClassName(String className) {
        this.className = className;
    }

    /**
     * @return Returns the done.
     */
    public boolean isDone() {
        return done;
    }

    /**
     * @param done The done to set.
     */
    public void setDone(boolean done) {
        this.done = done;
    }

    /**
     * @return Returns the methodName.
     */
    public String getMethodName() {
        return methodName;
    }

    /**
     * @param methodName The methodName to set.
     */
    public void setMethodName(String methodName) {
        this.methodName = methodName;
    }

    /**
     * @return Returns the methodParams.
     */
    public Object[] getMethodParams() {
        return methodParams;
    }

    /**
     * @param methodParams The methodParams to set.
     */
    public void setMethodParams(Object[] methodParams) {
        this.methodParams = methodParams;
    }

    /**
     * @return Returns the parmTypes.
     */
    public Class[] getParmTypes() {
        return parmTypes;
    }

    /**
     * @param parmTypes The parmTypes to set.
     */
    public void setParmTypes(Class[] parmTypes) {
        this.parmTypes = parmTypes;
    }

    /**
     * @return Returns the running.
     */
    public boolean isRunning() {
        return running;
    }

    /**
     * @param running The running to set.
     */
    public void setRunning(boolean running) {
        this.running = running;
    }

    /**
     * @return Returns the stopped.
     */
    public boolean isStopped() {
        return stopped;
    }

    /**
     * @param stopped The stopped to set.
     */
    public void setStopped(boolean stopped) {
        this.stopped = stopped;
    }

    /**
     * @return Returns the syncObject.
     */
    public Object getSyncObject() {
        return syncObject;
    }

    /**
     * @param syncObject The syncObject to set.
     */
    public void setSyncObject(Object syncObject) {
        this.syncObject = syncObject;
    }

    /**
     * execute
     * @param clsName
     * @param methName
     * @param params
     * @param synObj
     */
    public synchronized void execute(String clsName, String methName, Object[] params, Class[] paramTypes,
            Object synObj) {
        this.className = clsName;
        this.methodName = methName;
        this.methodParams = params;
        this.syncObject = synObj;
        this.parmTypes = paramTypes;
        this.done = false;

        if (!running) { //If this is the first time, then kick off the thread.
            this.setDaemon(true);
            this.start();
        } else { // we already have a thread running so wakeup the waiting thread.
            this.notifyAll();
        }
    }

    /* (non-Javadoc)
     * @see java.lang.Runnable#run()
     */
    public void run() {
        running = true;
        while (!stopped) {
            if (done) {
                synchronized (this) {
                    try {
                        this.wait();
                    } catch (InterruptedException e) {
                        stopped = true;
                        log.error("", e);
                    }
                }
            } else { //there is a task....let us execute it.
                try {
                    execute();
                } catch (Exception e) {
                    log.error("", e);
                } finally {
                    if (syncObject != null) {
                        synchronized (syncObject) {
                            syncObject.notify();
                        }
                    }
                    reset();
                    returnToPool();
                }
            }
        }
    }

    /** For  asynchronous execution, without waiting, the pool should be
     *  set, so that we can return the thread back to the pool. No need to use any
     * <code>wait()</code> or <code>notify()</code> methods.
     * see : <code>runAsyncTask()</code> method in PoolTester class.
     * <pre>
     *  Example : 
     *          ThreadPool pool = new ThreadPool(new ThreadObjectFactory());
     *          WorkerThread wt = (WorkerThread) pool.borrowObject();
     *          wt.setPool(pool);       wt.execute(.....) ;
     * </pre>
     */
    private void returnToPool() {
        if (pool != null) {
            try {
                pool.returnObject(this);
            } catch (Exception e1) {
                log.error("Exception :", e1);
            }
            this.pool = null;
        }
    }

    /**
     * reset the memebers to service next request.
     */
    public void reset() {
        this.done = true;
        this.className = null;
        this.methodName = null;
        this.methodParams = null;
        this.parmTypes = null;
        this.syncObject = null;
    }

    /**
     * getClass
     * @param cls
     * @return Class
     * @throws ClassNotFoundException  
     */
    private static Class getClass(String cls) throws ClassNotFoundException {
        ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
        if (classLoader == null) {
            classLoader = WorkerThread.class.getClassLoader();
        }
        return classLoader.loadClass(cls);
    }

    /**
     * execute
     */
    private void execute() {
        try {
            Class cls = getClass(this.getClassName());
            Object obj = cls.newInstance();
            this.result = MethodUtils.invokeExactMethod(obj, this.getMethodName(), this.getMethodParams(),
                    this.getParmTypes());
            log.debug(" #### Execution Result = " + result + " for : " + this);
        } catch (ClassNotFoundException e) {
            log.error("ClassNotFoundException - " + e);
        } catch (NoSuchMethodException e) {
            log.error("NoSuchMethodException - " + e);
        } catch (IllegalAccessException e) {
            log.error("IllegalAccessException - " + e);
        } catch (InvocationTargetException e) {
            log.error("InvocationTargetException - " + e);
        } catch (InstantiationException e) {
            log.error("InstantiationException - " + e);
        }
    }

}