1/*2 * Copyright 2000-2001,2004 The Apache Software Foundation.3 * 4 * Licensed under the Apache License, Version 2.0 (the "License");5 * you may not use this file except in compliance with the License.6 * You may obtain a copy of the License at7 * 8 * http://www.apache.org/licenses/LICENSE-2.09 * 10 * Unless required by applicable law or agreed to in writing, software11 * distributed under the License is distributed on an "AS IS" BASIS,12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.13 * See the License for the specific language governing permissions and14 * limitations under the License.15 */1617packageorg.apache.jetspeed.services.threadpool;
1819//turbine stuff20import org.apache.turbine.services.TurbineServices;
2122// Jetspeed classes23import org.apache.jetspeed.services.logging.JetspeedLogFactoryService;
24import org.apache.jetspeed.services.logging.JetspeedLogger;
2526/***27 * A thread that is used to process Runnables. This thread will wait until it is 28 * notified by another thread that it needs processing. However it will only 29 * process if getRunnable != null.30 *31 * @author <a href="mailto:burton@apache.org">Kevin A. Burton</a>32 * @author <a href="mailto:sgala@apache.org">Santiago Gala</a>33 * @version $Id: RunnableThread.java,v 1.7 2004/02/23 03:51:31 jford Exp $34 */35publicclassRunnableThreadextends Thread
36 {
37/***38 * Static initialization of the logger for this class39 */40privatestaticfinalJetspeedLogger logger = JetspeedLogFactoryService.getLogger(RunnableThread.class.getName());
4142privateboolean running = false;
43privatestaticint next_id = 0;
4445/***46 * Increment a counter so that we can identify threads47 * easily.48 */49privatestaticsynchronizedint getNextId() {
50return ++next_id;
51 };
52privateint id = 0;
5354/***55 The runnable that you want to process56 */57private Runnable runnable = null;
5859publicRunnableThread()
60 {
61super();
62this.setDaemon(true);
63 }
6465/***66 * Creates a new Thread in the specified threadgroup67 *68 * @param tg the Threadgroup which will contain the new Thread69 */70publicRunnableThread( ThreadGroup tg) {
71super( tg, "Provisory");
72this.id = getNextId();
73super.setName("RunnableThread:" + this.id );
74this.setPriority( Thread.MIN_PRIORITY );
75this.setDaemon(true);
7677 }
7879/***80 * Creates a new Thread in the specified threadgroup and assigns81 * it an id.82 *83 * @param tg the Threadgroup which will contain the new Thread84 * @param id an identifier for the new Thread85 */86publicRunnableThread( ThreadGroup tg,
87int id ) {
8889super( tg, "RunnableThread:" + id );
90this.setPriority( Thread.MIN_PRIORITY );
91this.setDaemon(true);
92this.id = id;
93 }
9495/***96 * Processes the Runnable object assigned to it, whenever one97 * is available98 */99publicvoid run() {
100101/*102 FIXME: move to a static class variable to allow for pool shutdown103 */104boolean poolrunning = true;
105while ( poolrunning ) {
106107108//On creation, we are idle.109//So, add ourselves to the Pool.110//Next times we come here, we are just finished111//one run...112this.setRunning( false );
113114this.setRunnable( null );
115116synchronized( this ) {
117if( this.getPriority() !=
118 JetspeedThreadPoolService.DEFAULT_THREAD_PRIORITY ) {
119//give the thread back it's default priority.120this.setPriority( JetspeedThreadPoolService.DEFAULT_THREAD_PRIORITY );
121 }
122123//SGP I don't think it is needed. The scheduler will do its job124//and the thread will be released sooner. Later, it will wait125//until the Pool reuses it. Correct me if I'm wrong126//but please comment the reasons, as I don't get it :)127128//yield this thread so that other threads can now execute129//if necessary.130//this.yield();131132//ok... add this thread back into the thread pool133 ( (JetspeedThreadPoolService)TurbineServices
134 .getInstance()
135 .getService( ThreadPoolService.SERVICE_NAME ) )
136 .release( this );
137138139//if the runnable == null wait because it has been not been140//directly assigned a task.. 141if ( this.getRunnable() == null ) {
142143try {
144this.wait();
145 } catch (InterruptedException e) {
146//this is a normal situation. 147//the DaemonFactory may want to stop this thread form 148//sleeping and call interrupt() on this thread.149 } catch ( Throwable t ) {
150 logger.error("Throwable", t);
151//continue;152 }
153154 }
155156 }
157158159if ( this.getRunnable() != null ) {
160this.setRunning( true );
161162try {
163164this.getRunnable().run();
165166 } catch ( Throwable t ) {
167 logger.error( "A problem occured while trying to run your thread", t );
168 }
169170 }
171172 }
173174 }
175176//misc getters/setters177178/***179 * Set the Runnable process to execute180 *181 * @param runnable the Object to execute182 */183publicvoid setRunnable( Runnable runnable ) {
184this.runnable = runnable;
185 }
186187/***188 * Get the Runnable process executing189 *190 * @return the Object executed by this thread191 */192public Runnable getRunnable() {
193returnthis.runnable;
194 }
195196/***197 * Test whether the thread is currently executing a process198 *199 * @return the status of this thread. If true, the thread is currently 200 * executing a Runnable process, if false it's waiting for a new process201 */202privateboolean isRunning() {
203returnthis.running;
204 }
205206/***207 * Set the running status of this thread.208 *209 * @return the status of this thread210 */211privatevoid setRunning( boolean running ) {
212this.running = running;
213 }
214215/***216 * Get the numeric identifier of this thread217 *218 * @return the identifier of the thread219 */220publicint getId() {
221returnthis.id;
222 }
223 }