KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > apache > avalon > excalibur > thread > impl > WorkerThread


1 /*
2  * Copyright (C) The Apache Software Foundation. All rights reserved.
3  *
4  * This software is published under the terms of the Apache Software License
5  * version 1.1, a copy of which has been included with this distribution in
6  * the LICENSE.txt file.
7  */

8 package org.apache.avalon.excalibur.thread.impl;
9
10 import org.apache.avalon.excalibur.lang.ThreadContext;
11 import org.apache.avalon.excalibur.pool.Poolable;
12 import org.apache.avalon.excalibur.pool.Pool;
13 import org.apache.avalon.excalibur.thread.ThreadControl;
14 import org.apache.avalon.framework.activity.Executable;
15 import org.apache.avalon.framework.logger.LogEnabled;
16 import org.apache.avalon.framework.logger.LogKitLogger;
17 import org.apache.avalon.framework.logger.Logger;
18
19 /**
20  * This class extends the Thread class to add recyclable functionalities.
21  *
22  * @author <a HREF="mailto:stefano@apache.org">Stefano Mazzocchi</a>
23  * @author <a HREF="mailto:peter@apache.org">Peter Donald</a>
24  */

25 class WorkerThread
26     extends Thread JavaDoc
27     implements Poolable, LogEnabled
28 {
29     private Logger m_logger;
30     private Pool m_pool;
31
32     private Executable m_work;
33     private DefaultThreadControl m_threadControl;
34     private ThreadContext m_context;
35     private boolean m_alive;
36
37     /**
38      * Allocates a new <code>Worker</code> object.
39      */

40     protected WorkerThread( final ThreadGroup JavaDoc group,
41                             final String JavaDoc name,
42                             final Pool pool,
43                             final ThreadContext context )
44     {
45         super( group, name );
46
47         m_pool = pool;
48         m_context = context;
49
50         m_work = null;
51
52         m_alive = true;
53
54         setDaemon( false );
55     }
56
57     public void enableLogging( final Logger logger )
58     {
59         m_logger = logger;
60     }
61
62     /**
63      * The main execution loop.
64      */

65     public final synchronized void run()
66     {
67         debug( "starting." );
68
69         // Notify the pool this worker started running.
70
//notifyAll();
71

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

128     public void dispose()
129     {
130         debug( "destroying." );
131         m_alive = false;
132         waitUntilCondition( false );
133     }
134
135     protected synchronized ThreadControl execute( final Executable work )
136     {
137         m_work = work;
138         m_threadControl = new DefaultThreadControl( this );
139
140         debug( "notifying this worker." );
141         notify();
142
143         return m_threadControl;
144     }
145
146     /**
147      * Set the <code>Work</code> code this <code>Worker</code> must
148      * execute and <i>notifies</i> its thread to do it.
149      */

150     protected synchronized void executeAndWait( final Executable work )
151     {
152         execute( work );
153         waitUntilCondition( false );
154     }
155
156     private synchronized void waitUntilCondition( final boolean hasWork )
157     {
158         while( hasWork == (null == m_work) )
159         {
160             try
161             {
162                 debug( "waiting." );
163                 wait();
164                 debug( "notified." );
165             }
166             catch( final InterruptedException JavaDoc ie ) {}
167         }
168     }
169
170     private void debug( final String JavaDoc message )
171     {
172         if( false )
173         {
174             final String JavaDoc output = getName() + ": " + message;
175             m_logger.debug( output );
176             //System.out.println( output );
177
}
178     }
179 }
180
Popular Tags