donaldp 2002/09/28 01:27:05
Added: thread/src/java/org/apache/excalibur/thread/impl
WorkerThread.java
Log:
Add in a WorkerThread that can be used to
actually do the work. Derived from original
code but decoupled from Avalon, cleaned up
extensively and made sub-class friendly.
Revision Changes Path
1.1
jakarta-avalon-excalibur/thread/src/java/org/apache/excalibur/thread/impl/WorkerThread.java
Index: WorkerThread.java
===================================================================
/*
* Copyright (C) The Apache Software Foundation. All rights reserved.
*
* This software is published under the terms of the Apache Software License
* version 1.1, a copy of which has been included with this distribution in
* the LICENSE.txt file.
*/
package org.apache.excalibur.thread.impl;
import org.apache.excalibur.thread.Executable;
import org.apache.excalibur.thread.ThreadControl;
/**
* This class extends the Thread class to add recyclable functionalities.
*
* @author <a href="mailto:[EMAIL PROTECTED]">Stefano Mazzocchi</a>
* @author <a href="mailto:peter at apache.org">Peter Donald</a>
*/
public class WorkerThread
extends Thread
{
/**
* The work currentlyy associated with worker (May be null).
*/
private Executable m_work;
/**
* The thread control associated with current work.
* Should be null if work is null.
*/
private DefaultThreadControl m_threadControl;
/**
* True if this thread is alive and not scheduled for shutdown.
*/
private boolean m_alive;
/**
* The name of thread.
*/
private final String m_name;
/**
* The thread pool this thread is associated with.
*/
private final AbstractThreadPool m_pool;
/**
* Allocates a new <code>Worker</code> object.
*/
protected WorkerThread( final AbstractThreadPool pool,
final ThreadGroup group,
final String name )
{
super( group, "" );
if( null == name )
{
throw new NullPointerException( "name" );
}
if( null == pool )
{
throw new NullPointerException( "pool" );
}
m_name = name;
m_work = null;
m_alive = true;
m_pool = pool;
setDaemon( false );
}
/**
* The main execution loop.
*/
public final synchronized void run()
{
debug( "starting." );
// Notify the pool this worker started running.
//notifyAll();
while( m_alive )
{
waitUntilCondition( true );
debug( "running." );
try
{
preExecute();
m_work.execute();
m_threadControl.finish( null );
}
catch( final ThreadDeath threadDeath )
{
debug( "thread has died." );
m_threadControl.finish( threadDeath );
// This is to let the thread death propagate to the runtime
// enviroment to let it know it must kill this worker
throw threadDeath;
}
catch( final Throwable throwable )
{
// Error thrown while working.
debug( "error caught: " + throwable );
m_threadControl.finish( throwable );
}
finally
{
debug( "done." );
m_work = null;
m_threadControl = null;
postExecute();
}
//should this be just notify or notifyAll ???
//It seems to resource intensive option to use notify()
//notifyAll();
notify();
// recycle ourselves
recycleThread();
}
}
/**
* Implement this method to replace thread back into pool.
*/
protected void recycleThread()
{
if( m_alive )
{
m_pool.releaseWorker( this );
}
}
/**
* Overide this method to execute something after
* each bit of "work".
*/
protected void postExecute()
{
}
/**
* Overide this method to execute something before
* each bit of "work".
*/
protected void preExecute()
{
//TODO: Thread name setting should reuse the
//ThreadContext code if ThreadContext used.
Thread.currentThread().setName( m_name );
}
/**
* Set the <tt>alive</tt> variable to false causing the worker to die.
* If the worker is stalled and a timeout generated this call, this method
* does not change the state of the worker (that must be destroyed in other
* ways).
*/
public void dispose()
{
debug( "destroying." );
m_alive = false;
waitUntilCondition( false );
}
/**
* Set the <tt>Work</tt> code this <tt>Worker</tt> must
* execute and <i>notifies</i> its thread to do it.
*/
protected synchronized ThreadControl execute( final Executable work )
{
m_work = work;
m_threadControl = new DefaultThreadControl( this );
debug( "notifying this worker." );
notify();
return m_threadControl;
}
/**
* Set the <tt>Work</tt> code this <tt>Worker</tt> must
* execute and <i>notifies</i> its thread to do it. Wait
* until the executable has finished before returning.
*/
protected synchronized void executeAndWait( final Executable work )
{
execute( work );
waitUntilCondition( false );
}
/**
* Wait until the worker either has work or doesn't have work.
*
* @param hasWork true if waiting till work is present, false otherwise
*/
private synchronized void waitUntilCondition( final boolean hasWork )
{
while( hasWork == ( null == m_work ) )
{
try
{
debug( "waiting." );
wait();
debug( "notified." );
}
catch( final InterruptedException ie )
{
}
}
}
/**
* Write a debug message.
* A Noop oin this implementation. Subclasses can overide
* to actually do some logging.
*
* @param message the message to write out
*/
protected void debug( final String message )
{
if( false )
{
final String output = getName() + ": " + message;
System.out.println( output );
}
}
}
--
To unsubscribe, e-mail: <mailto:[EMAIL PROTECTED]>
For additional commands, e-mail: <mailto:[EMAIL PROTECTED]>