KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > apache > james > util > thread > WorkerThread


1 /***********************************************************************
2  * Copyright (c) 1999-2004 The Apache Software Foundation. *
3  * All rights reserved. *
4  * ------------------------------------------------------------------- *
5  * Licensed under the Apache License, Version 2.0 (the "License"); you *
6  * may not use this file except in compliance with the License. You *
7  * may obtain a copy of the License at: *
8  * *
9  * http://www.apache.org/licenses/LICENSE-2.0 *
10  * *
11  * Unless required by applicable law or agreed to in writing, software *
12  * distributed under the License is distributed on an "AS IS" BASIS, *
13  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or *
14  * implied. See the License for the specific language governing *
15  * permissions and limitations under the License. *
16  ***********************************************************************/

17
18 package org.apache.james.util.thread;
19
20 import org.apache.avalon.excalibur.pool.Pool;
21 import org.apache.avalon.excalibur.pool.Poolable;
22 import org.apache.avalon.excalibur.thread.ThreadControl;
23 import org.apache.avalon.framework.activity.Executable;
24 import org.apache.avalon.framework.logger.LogEnabled;
25 import org.apache.avalon.framework.logger.Logger;
26 import org.apache.excalibur.threadcontext.ThreadContext;
27
28 /**
29  * This class extends the Thread class to add recyclable functionalities.
30  *
31  */

32 class WorkerThread
33    extends Thread JavaDoc
34    implements Poolable, LogEnabled
35 {
36        private Logger m_logger;
37        private Pool m_pool;
38
39        private Executable m_work;
40        private DefaultThreadControl m_threadControl;
41        private ThreadContext m_context;
42        private boolean m_alive;
43
44        private String JavaDoc m_name;
45
46     /**
47      * Allocates a new <code>Worker</code> object.
48      */

49        protected WorkerThread( final ThreadGroup JavaDoc group,
50                                final String JavaDoc name,
51                                final Pool pool,
52                                final ThreadContext context )
53        {
54            super( group, "" );
55            m_name = name;
56            m_pool = pool;
57            m_context = context;
58            m_work = null;
59            m_alive = true;
60
61            setDaemon( false );
62        }
63
64        public void enableLogging( final Logger logger )
65        {
66            m_logger = logger;
67        }
68
69     /**
70      * The main execution loop.
71      */

72        public final synchronized void run()
73        {
74            debug( "starting." );
75
76         // Notify the pool this worker started running.
77
//notifyAll();
78

79            while( m_alive )
80            {
81                waitUntilCondition( true );
82
83                debug( "running." );
84
85                try
86                {
87                 //TODO: Thread name setting should reuse the ThreadContext code.
88
Thread.currentThread().setName( m_name );
89                    if( null != m_context ) ThreadContext.setThreadContext( m_context );
90                    m_work.execute();
91                    m_threadControl.finish( null );
92                }
93                catch( final ThreadDeath JavaDoc threadDeath )
94                {
95                    debug( "thread has died." );
96                    m_threadControl.finish( threadDeath );
97                 // This is to let the thread death propagate to the runtime
98
// enviroment to let it know it must kill this worker
99
throw threadDeath;
100                }
101                catch( final Throwable JavaDoc throwable )
102                {
103                 // Error thrown while working.
104
debug( "error caught: " + throwable );
105                    m_threadControl.finish( throwable );
106                }
107                finally
108                {
109                    debug( "done." );
110                    m_work = null;
111                    m_threadControl = null;
112                    if( null != m_context ) ThreadContext.setThreadContext( null );
113                }
114
115             //should this be just notify or notifyAll ???
116
//It seems to resource intensive option to use notify()
117
//notifyAll();
118
notify();
119
120             // recycle ourselves
121
if( null != m_pool )
122                {
123                    m_pool.put( this );
124                }
125                else
126                {
127                    m_alive = false;
128                }
129            }
130        }
131
132     /**
133      * Set the <code>alive</code> variable to false causing the worker to die.
134      * If the worker is stalled and a timeout generated this call, this method
135      * does not change the state of the worker (that must be destroyed in other
136      * ways).
137      */

138        public void dispose()
139        {
140            debug( "destroying." );
141            m_alive = false;
142            waitUntilCondition( false );
143        }
144
145        protected synchronized ThreadControl execute( final Executable work )
146        {
147            m_work = work;
148            m_threadControl = new DefaultThreadControl( this );
149
150            debug( "notifying this worker." );
151            notify();
152
153            return m_threadControl;
154        }
155
156     /**
157      * Set the <code>Work</code> code this <code>Worker</code> must
158      * execute and <i>notifies</i> its thread to do it.
159      */

160        protected synchronized void executeAndWait( final Executable work )
161        {
162            execute( work );
163            waitUntilCondition( false );
164        }
165
166        private synchronized void waitUntilCondition( final boolean hasWork )
167        {
168            while( hasWork == ( null == m_work ) )
169            {
170                try
171                {
172                    debug( "waiting." );
173                    wait();
174                    debug( "notified." );
175                }
176                catch( final InterruptedException JavaDoc ie )
177                {
178                }
179            }
180        }
181
182        private void debug( final String JavaDoc message )
183        {
184            if( false )
185            {
186                final String JavaDoc output = getName() + ": " + message;
187                m_logger.debug( output );
188             //System.out.println( output );
189
}
190        }
191 }
192
Popular Tags