KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > apache > cocoon > components > thread > DefaultRunnableManager


1 /*
2  * Copyright 1999-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 at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * 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 and
14  * limitations under the License.
15  */

16 package org.apache.cocoon.components.thread;
17
18 import org.apache.avalon.framework.activity.Disposable;
19 import org.apache.avalon.framework.activity.Startable;
20 import org.apache.avalon.framework.configuration.Configurable;
21 import org.apache.avalon.framework.configuration.Configuration;
22 import org.apache.avalon.framework.configuration.ConfigurationException;
23 import org.apache.avalon.framework.logger.AbstractLogEnabled;
24 import org.apache.avalon.framework.logger.Logger;
25 import org.apache.avalon.framework.thread.ThreadSafe;
26
27 import java.util.HashMap JavaDoc;
28 import java.util.Iterator JavaDoc;
29 import java.util.Map JavaDoc;
30 import java.util.SortedSet JavaDoc;
31 import java.util.TreeSet JavaDoc;
32
33 /**
34  * The DefaultRunnableManager implements the {@link RunnableManager} interface
35  * and is responsible to create {@link ThreadPool}s and run {@link Runnable}s
36  * in them as background commands.
37  *
38  * <p>
39  * The configuration of the <code>DefaultRunnableManager</code>:
40  * <pre>
41  * &lt;thread-factory&gt;org.apache.cocoon.components.thread.DefaultThreadFactory&lt;/thread-factory&gt;
42  * &lt;thread-pools&gt;
43  * &lt;thread-pool&gt;
44  * &lt;name&gt;default&lt;/name&gt;
45  * &lt;priority&gt;NORM&lt;/priority&gt;
46  * &lt;daemon&gt;false&lt;/daemon&gt;
47  * &lt;queue-size&gt;-1&lt;/queue-size&gt;
48  * &lt;max-pool-size&gt;-1&lt;/max-pool-size&gt;
49  * &lt;min-pool-size&gt;2&lt;/min-pool-size&gt;
50  * &lt;keep-alive-time-ms&gt;20000&lt;/keep-alive-time-ms&gt;
51  * &lt;block-policy&gt;RUN&lt;/block-policy&gt;
52  * &lt;shutdown-graceful&gt;false&lt;/shutdown-graceful&gt;
53  * &lt;shutdown-wait-time-ms&gt;-1&lt;/shutdown-wait-time-ms&gt;
54  * &lt;/thread-pool&gt;
55  * &lt;/thread-pools&gt;
56  * </pre>
57  * </p>
58  *
59  * <p>
60  * Have a look at
61  * http://gee.cs.oswego.edu/dl/classes/EDU/oswego/cs/dl/util/concurrent/PooledExecutor.html,
62  * {@link EDU.oswego.cs.dl.util.concurrent.PooledExecutor} or the cocoon.xconf
63  * file for more information.
64  * </p>
65  *
66  * @author <a HREF="mailto:giacomo.at.apache.org">Giacomo Pati</a>
67  * @version $Id: DefaultRunnableManager.java 56848 2004-11-07 14:09:23Z giacomo $
68  */

69 public class DefaultRunnableManager
70     extends AbstractLogEnabled
71     implements RunnableManager, Configurable, Disposable, Runnable JavaDoc, Startable,
72                    ThreadSafe
73 {
74     //~ Static fields/initializers ---------------------------------------------
75

76     /** The default {@link ThreadFactory} */
77     public static final String JavaDoc DEFAULT_THREAD_FACTORY =
78         DefaultThreadFactory.class.getName( );
79
80     /** The default queue size */
81     public static final int DEFAULT_QUEUE_SIZE = -1;
82
83     /** The default maximum pool size */
84     public static final int DEFAULT_MAX_POOL_SIZE = 5;
85
86     /** The default minimum pool size */
87     public static final int DEFAULT_MIN_POOL_SIZE = 5;
88
89     /** The default thread priority */
90     public static final String JavaDoc DEFAULT_THREAD_PRIORITY = "NORM";
91
92     /** The default daemon mode */
93     public static final boolean DEFAULT_DAEMON_MODE = false;
94
95     /** The default keep alive time */
96     public static final long DEFAULT_KEEP_ALIVE_TIME = 60000L;
97
98     /** The default way to shutdown gracefully */
99     public static final boolean DEFAULT_SHUTDOWN_GRACEFUL = false;
100
101     /** The default shutdown waittime time */
102     public static final int DEFAULT_SHUTDOWN_WAIT_TIME = -1;
103
104     /** The default shutdown waittime time */
105     public static final String JavaDoc DEFAULT_THREADPOOL_NAME = "default";
106
107     //~ Instance fields --------------------------------------------------------
108

109     /**
110      * Sorted set of <code>ExecutionInfo</code> instances, based on their next
111      * execution time.
112      */

113     protected SortedSet JavaDoc m_commandStack = new TreeSet JavaDoc( );
114
115     /** The managed thread pools */
116     final Map JavaDoc m_pools = new HashMap JavaDoc( );
117
118     /** The configured default ThreadFactory class instance */
119     private Class JavaDoc m_defaultThreadFactoryClass;
120
121     /** Keep us running? */
122     private boolean m_keepRunning = false;
123
124     //~ Methods ----------------------------------------------------------------
125

126     /**
127      * @see org.apache.avalon.framework.configuration.Configurable#configure(org.apache.avalon.framework.configuration.Configuration)
128      */

129     public void configure( final Configuration config )
130         throws ConfigurationException
131     {
132         final String JavaDoc defaultThreadFactoryName =
133             config.getChild( "thread-factory" ).getValue( DEFAULT_THREAD_FACTORY );
134
135         try
136         {
137             m_defaultThreadFactoryClass =
138                 Thread.currentThread( ).getContextClassLoader( ).loadClass( defaultThreadFactoryName );
139         }
140         catch( final Exception JavaDoc ex )
141         {
142             throw new ConfigurationException( "Cannot create instance of default thread factory " +
143                                               defaultThreadFactoryName, ex );
144         }
145
146         final Configuration [] threadpools =
147             config.getChild( "thread-pools" ).getChildren( "thread-pool" );
148
149         for( int i = 0; i < threadpools.length; i++ )
150         {
151             final DefaultThreadPool pool = configThreadPool( threadpools[ i ] );
152         }
153
154         // Check if a "default" pool has been created
155
final ThreadPool defaultThreadPool =
156             (ThreadPool)m_pools.get( DEFAULT_THREADPOOL_NAME );
157
158         if( null == defaultThreadPool )
159         {
160             createPool( DEFAULT_THREADPOOL_NAME, DEFAULT_QUEUE_SIZE,
161                         DEFAULT_MAX_POOL_SIZE, DEFAULT_MIN_POOL_SIZE,
162                         getPriority( DEFAULT_THREAD_PRIORITY ),
163                         DEFAULT_DAEMON_MODE, DEFAULT_KEEP_ALIVE_TIME,
164                         DefaultThreadPool.POLICY_DEFAULT,
165                         DEFAULT_SHUTDOWN_GRACEFUL, DEFAULT_SHUTDOWN_WAIT_TIME );
166         }
167     }
168
169     /**
170      * Create a shared ThreadPool
171      *
172      * @param name The name of the thread pool
173      * @param queueSize The size of the queue
174      * @param maxPoolSize The maximum number of threads
175      * @param minPoolSize The maximum number of threads
176      * @param priority The priority of threads created by this pool. This is
177      * one of {@link Thread#MIN_PRIORITY}, {@link
178      * Thread#NORM_PRIORITY}, or {@link Thread#MAX_PRIORITY}
179      * @param isDaemon Whether or not thread from the pool should run in daemon
180      * mode
181      * @param keepAliveTime How long should a thread be alive for new work to
182      * be done before it is GCed
183      * @param blockPolicy What's the blocking policy is resources are exhausted
184      * @param shutdownGraceful Should we wait for the queue to finish all
185      * pending commands?
186      * @param shutdownWaitTime After what time a normal shutdown should take
187      * into account if a graceful shutdown has not come to an end
188      *
189      * @throws IllegalArgumentException If the pool already exists
190      */

191     public void createPool( final String JavaDoc name,
192                             final int queueSize,
193                             final int maxPoolSize,
194                             final int minPoolSize,
195                             final int priority,
196                             final boolean isDaemon,
197                             final long keepAliveTime,
198                             final String JavaDoc blockPolicy,
199                             final boolean shutdownGraceful,
200                             final int shutdownWaitTime )
201     {
202         if( null != m_pools.get( name ) )
203         {
204             throw new IllegalArgumentException JavaDoc( "ThreadPool \"" + name +
205                                                 "\" already exists" );
206         }
207
208         createPool( new DefaultThreadPool( ), name, queueSize, maxPoolSize,
209                     minPoolSize, priority, isDaemon, keepAliveTime,
210                     blockPolicy, shutdownGraceful, shutdownWaitTime );
211     }
212
213     /**
214      * Create a private ThreadPool
215      *
216      * @param queueSize The size of the queue
217      * @param maxPoolSize The maximum number of threads
218      * @param minPoolSize The maximum number of threads
219      * @param priority The priority of threads created by this pool. This is
220      * one of {@link Thread#MIN_PRIORITY}, {@link
221      * Thread#NORM_PRIORITY}, or {@link Thread#MAX_PRIORITY}
222      * @param isDaemon Whether or not thread from the pool should run in daemon
223      * mode
224      * @param keepAliveTime How long should a thread be alive for new work to
225      * be done before it is GCed
226      * @param blockPolicy What's the blocking policy is resources are exhausted
227      * @param shutdownGraceful Should we wait for the queue to finish all
228      * pending commands?
229      * @param shutdownWaitTime After what time a normal shutdown should take
230      * into account if a graceful shutdown has not come to an end
231      *
232      * @return A newly created <code>ThreadPool</code>
233      */

234     public ThreadPool createPool( final int queueSize,
235                                   final int maxPoolSize,
236                                   final int minPoolSize,
237                                   final int priority,
238                                   final boolean isDaemon,
239                                   final long keepAliveTime,
240                                   final String JavaDoc blockPolicy,
241                                   final boolean shutdownGraceful,
242                                   final int shutdownWaitTime )
243     {
244         final DefaultThreadPool pool = new DefaultThreadPool( );
245         final String JavaDoc name = "anon-" + pool.hashCode( );
246
247         return createPool( pool, name, queueSize, maxPoolSize, minPoolSize,
248                            priority, isDaemon, keepAliveTime, blockPolicy,
249                            shutdownGraceful, shutdownWaitTime );
250     }
251
252     /**
253      * @see org.apache.avalon.framework.activity.Disposable#dispose()
254      */

255     public void dispose( )
256     {
257         if( getLogger( ).isDebugEnabled( ) )
258         {
259             getLogger( ).debug( "Disposing all thread pools" );
260         }
261
262         for( final Iterator JavaDoc i = m_pools.keySet( ).iterator( ); i.hasNext( ); )
263         {
264             final String JavaDoc poolName = (String JavaDoc)i.next( );
265             final DefaultThreadPool pool =
266                 (DefaultThreadPool)m_pools.get( poolName );
267
268             if( getLogger( ).isDebugEnabled( ) )
269             {
270                 getLogger( ).debug( "Disposing thread pool " +
271                                      pool.getName( ) );
272             }
273
274             pool.shutdown( );
275
276             if( getLogger( ).isDebugEnabled( ) )
277             {
278                 getLogger( ).debug( "Thread pool " + pool.getName( ) +
279                                      " disposed" );
280             }
281         }
282
283         try
284         {
285             m_pools.clear( );
286         }
287         catch( final Throwable JavaDoc t )
288         {
289             getLogger( ).error( "Cannot dispose", t );
290         }
291     }
292
293     /**
294      * Run a {@link Runnable} in the background using a {@link ThreadPool}
295      *
296      * @param threadPoolName The thread pool name to be used
297      * @param command The {@link Runnable} to execute
298      * @param delay the delay befor first run
299      * @param interval The interval for repeated runs
300      *
301      * @throws IllegalArgumentException DOCUMENT ME!
302      */

303     public void execute( final String JavaDoc threadPoolName,
304                          final Runnable JavaDoc command,
305                          final long delay,
306                          long interval )
307     {
308         if( delay < 0 )
309         {
310             throw new IllegalArgumentException JavaDoc( "delay < 0" );
311         }
312
313         if( interval < 0 )
314         {
315             throw new IllegalArgumentException JavaDoc( "interval < 0" );
316         }
317
318         ThreadPool pool = (ThreadPool)m_pools.get( threadPoolName );
319
320         if( null == pool )
321         {
322             getLogger( ).warn( "ThreadPool \"" + threadPoolName +
323                                 "\" is not known. Will use ThreadPool \"" +
324                                 DEFAULT_THREADPOOL_NAME + "\"" );
325             pool = (ThreadPool)m_pools.get( DEFAULT_THREADPOOL_NAME );
326         }
327
328         if( getLogger( ).isDebugEnabled( ) )
329         {
330             getLogger( ).debug( "Command entered: " + command.toString( ) +
331                                  ", pool=" + pool.getName( ) + ", delay=" +
332                                  delay + ", interval=" + interval );
333         }
334
335         new ExecutionInfo( pool, command, delay, interval, getLogger( ) );
336     }
337
338     /**
339      * Run a {@link Runnable} in the background using a {@link ThreadPool}
340      *
341      * @param command The {@link Runnable} to execute
342      * @param delay the delay befor first run
343      * @param interval The interval for repeated runs
344      */

345     public void execute( final Runnable JavaDoc command,
346                          final long delay,
347                          final long interval )
348     {
349         execute( DEFAULT_THREADPOOL_NAME, command, delay, interval );
350     }
351
352     /**
353      * Run a {@link Runnable} in the background using a {@link ThreadPool}
354      *
355      * @param command The {@link Runnable} to execute
356      * @param delay the delay befor first run
357      */

358     public void execute( final Runnable JavaDoc command,
359                          final long delay )
360     {
361         execute( DEFAULT_THREADPOOL_NAME, command, delay, 0 );
362     }
363
364     /**
365      * Run a {@link Runnable} in the background using a {@link ThreadPool}
366      *
367      * @param command The {@link Runnable} to execute
368      */

369     public void execute( final Runnable JavaDoc command )
370     {
371         execute( DEFAULT_THREADPOOL_NAME, command, 0, 0 );
372     }
373
374     /**
375      * Run a {@link Runnable} in the background using a {@link ThreadPool}
376      *
377      * @param threadPoolName The thread pool name to be used
378      * @param command The {@link Runnable} to execute
379      * @param delay the delay befor first run
380      */

381     public void execute( final String JavaDoc threadPoolName,
382                          final Runnable JavaDoc command,
383                          final long delay )
384     {
385         execute( threadPoolName, command, delay, 0 );
386     }
387
388     /**
389      * Run a {@link Runnable} in the background using a {@link ThreadPool}
390      *
391      * @param threadPoolName The thread pool name to be used
392      * @param command The {@link Runnable} to execute
393      */

394     public void execute( final String JavaDoc threadPoolName,
395                          final Runnable JavaDoc command )
396     {
397         execute( threadPoolName, command, 0, 0 );
398     }
399
400     /**
401      * Remove a <code>Runnable</code> from the command stack
402      *
403      * @param command The <code>Runnable</code> to be removed
404      */

405     public void remove( Runnable JavaDoc command )
406     {
407         synchronized( m_commandStack )
408         {
409             for( final Iterator JavaDoc i = m_commandStack.iterator( ); i.hasNext( ); )
410             {
411                 final ExecutionInfo info = (ExecutionInfo)i.next( );
412
413                 if( info.m_command == command )
414                 {
415                     i.remove( );
416                     m_commandStack.notifyAll( );
417
418                     return;
419                 }
420             }
421         }
422
423         getLogger( ).warn( "Could not find command " + command +
424                             " for removal" );
425     }
426
427     /**
428      * The heart of the command manager
429      */

430     public void run( )
431     {
432         if( getLogger( ).isDebugEnabled( ) )
433         {
434             getLogger( ).debug( "Entering loop" );
435         }
436
437         while( m_keepRunning )
438         {
439             synchronized( m_commandStack )
440             {
441                 try
442                 {
443                     if( m_commandStack.size( ) > 0 )
444                     {
445                         final ExecutionInfo info =
446                             (ExecutionInfo)m_commandStack.first( );
447                         final long delay =
448                             info.m_nextRun - System.currentTimeMillis( );
449
450                         if( delay > 0 )
451                         {
452                             m_commandStack.wait( delay );
453                         }
454                     }
455                     else
456                     {
457                         if( getLogger( ).isDebugEnabled( ) )
458                         {
459                             getLogger( ).debug( "No commands available. Will just wait for one" );
460                         }
461
462                         m_commandStack.wait( );
463                     }
464                 }
465                 catch( final InterruptedException JavaDoc ie )
466                 {
467                     if( getLogger( ).isDebugEnabled( ) )
468                     {
469                         getLogger( ).debug( "I've been interrupted" );
470                     }
471                 }
472
473                 if( m_keepRunning )
474                 {
475                     if( m_commandStack.size( ) > 0 )
476                     {
477                         final ExecutionInfo info =
478                             (ExecutionInfo)m_commandStack.first( );
479                         final long delay =
480                             info.m_nextRun - System.currentTimeMillis( );
481
482                         if( delay < 0 )
483                         {
484                             info.execute( );
485                         }
486                     }
487                 }
488             }
489         }
490
491         if( getLogger( ).isDebugEnabled( ) )
492         {
493             getLogger( ).debug( "Exiting loop" );
494         }
495     }
496
497     /**
498      * Start the managing thread
499      *
500      * @throws Exception DOCUMENT ME!
501      */

502     public void start( ) throws Exception JavaDoc
503     {
504         if( getLogger( ).isDebugEnabled( ) )
505         {
506             getLogger( ).debug( "Starting the heart" );
507         }
508
509         m_keepRunning = true;
510         ( (ThreadPool) m_pools.get( DEFAULT_THREADPOOL_NAME ) ).execute( this );
511     }
512
513     /**
514      * Stop the managing thread
515      *
516      * @throws Exception DOCUMENT ME!
517      */

518     public void stop( )
519         throws Exception JavaDoc
520     {
521         m_keepRunning = false;
522
523         synchronized( m_commandStack )
524         {
525             m_commandStack.notifyAll( );
526         }
527     }
528
529     /**
530      * DOCUMENT ME!
531      *
532      * @param priority The priority to set as string value.
533      *
534      * @return The priority as int value.
535      */

536     private int getPriority( final String JavaDoc priority )
537     {
538         if( "MIN".equalsIgnoreCase( priority ) )
539         {
540             return Thread.MIN_PRIORITY;
541         }
542         else if( "NORM".equalsIgnoreCase( priority ) )
543         {
544             return Thread.NORM_PRIORITY;
545         }
546         else if( "MAX".equalsIgnoreCase( priority ) )
547         {
548             return Thread.MAX_PRIORITY;
549         }
550         else
551         {
552             getLogger( ).warn( "Unknown thread priority \"" + priority +
553                                 "\". Set to \"NORM\"." );
554
555             return Thread.NORM_PRIORITY;
556         }
557     }
558
559     /**
560      * DOCUMENT ME!
561      *
562      * @param config DOCUMENT ME!
563      *
564      * @return DOCUMENT ME!
565      *
566      * @throws ConfigurationException DOCUMENT ME!
567      */

568     private DefaultThreadPool configThreadPool( final Configuration config )
569         throws ConfigurationException
570     {
571         final String JavaDoc name = config.getChild( "name" ).getValue( );
572         final int queueSize =
573             config.getChild( "queue-size" ).getValueAsInteger( DEFAULT_QUEUE_SIZE );
574         final int maxPoolSize =
575             config.getChild( "max-pool-size" ).getValueAsInteger( DEFAULT_MAX_POOL_SIZE );
576         int minPoolSize =
577             config.getChild( "min-pool-size" ).getValueAsInteger( DEFAULT_MIN_POOL_SIZE );
578
579         // make sure we have enough threads for the default thread pool as we
580
// need one for ourself
581
if( DEFAULT_THREADPOOL_NAME.equals( name ) &&
582             ( ( minPoolSize > 0 ) && ( minPoolSize < DEFAULT_MIN_POOL_SIZE ) ) )
583         {
584             minPoolSize = DEFAULT_MIN_POOL_SIZE;
585         }
586
587         final String JavaDoc priority =
588             config.getChild( "priority" ).getValue( DEFAULT_THREAD_PRIORITY );
589         final boolean isDaemon =
590             config.getChild( "daemon" ).getValueAsBoolean( DEFAULT_DAEMON_MODE );
591         final long keepAliveTime =
592             config.getChild( "keep-alive-time-ms" ).getValueAsLong( DEFAULT_KEEP_ALIVE_TIME );
593         final String JavaDoc blockPolicy =
594             config.getChild( "block-policy" ).getValue( DefaultThreadPool.POLICY_DEFAULT );
595         final boolean shutdownGraceful =
596             config.getChild( "shutdown-graceful" ).getValueAsBoolean( DEFAULT_SHUTDOWN_GRACEFUL );
597         final int shutdownWaitTime =
598             config.getChild( "shutdown-wait-time-ms" ).getValueAsInteger( DEFAULT_SHUTDOWN_WAIT_TIME );
599
600         return createPool( new DefaultThreadPool( ), name, queueSize,
601                            maxPoolSize, minPoolSize, getPriority( priority ),
602                            isDaemon, keepAliveTime, blockPolicy,
603                            shutdownGraceful, shutdownWaitTime );
604     }
605
606     /**
607      * Create a ThreadPool
608      *
609      * @param pool DOCUMENT ME!
610      * @param name DOCUMENT ME!
611      * @param queueSize The size of the queue
612      * @param maxPoolSize The maximum number of threads
613      * @param minPoolSize The maximum number of threads
614      * @param priority The priority of threads created by this pool. This is
615      * one of {@link Thread#MIN_PRIORITY}, {@link
616      * Thread#NORM_PRIORITY}, or {@link Thread#MAX_PRIORITY}
617      * @param isDaemon Whether or not thread from the pool should run in daemon
618      * mode
619      * @param keepAliveTime How long should a thread be alive for new work to
620      * be done before it is GCed
621      * @param blockPolicy What's the blocking policy is resources are exhausted
622      * @param shutdownGraceful Should we wait for the queue to finish all
623      * pending commands?
624      * @param shutdownWaitTime After what time a normal shutdown should take
625      * into account if a graceful shutdown has not come to an end
626      *
627      * @return A newly created <code>ThreadPool</code>
628      */

629     private DefaultThreadPool createPool( final DefaultThreadPool pool,
630                                           final String JavaDoc name,
631                                           final int queueSize,
632                                           final int maxPoolSize,
633                                           final int minPoolSize,
634                                           final int priority,
635                                           final boolean isDaemon,
636                                           final long keepAliveTime,
637                                           final String JavaDoc blockPolicy,
638                                           final boolean shutdownGraceful,
639                                           final int shutdownWaitTime )
640     {
641         pool.enableLogging( getLogger( ).getChildLogger( name ) );
642         pool.setName( name );
643
644         ThreadFactory factory = null;
645         try
646         {
647             factory =
648                 (ThreadFactory)m_defaultThreadFactoryClass.newInstance( );
649         }
650         catch( final Exception JavaDoc ex )
651         {
652             getLogger( ).warn( "Cannot instantiate a ThreadFactory from class " +
653                                 m_defaultThreadFactoryClass.getName( ) +
654                                 ". Will use a " +
655                                 DefaultThreadFactory.class.getName( ), ex );
656             factory = new DefaultThreadFactory( );
657         }
658
659         factory.setPriority( priority );
660         factory.setDaemon( isDaemon );
661         pool.setThreadFactory( factory );
662         pool.setQueue( queueSize );
663         pool.setMaximumPoolSize( ( maxPoolSize < 0 ) ? Integer.MAX_VALUE
664                                  : maxPoolSize );
665
666         if( minPoolSize < 1 )
667         {
668             getLogger( ).warn( "min-pool-size < 1 for pool \"" +
669                                 name + "\". Set to 1" );
670         }
671
672         pool.setMinimumPoolSize( ( minPoolSize < 1 ) ? 1 : minPoolSize );
673
674         if( keepAliveTime < 0 )
675         {
676             getLogger( ).warn( "keep-alive-time-ms < 0 for pool \"" +
677                                 name + "\". Set to 1000" );
678         }
679
680         pool.setKeepAliveTime( ( keepAliveTime < 0 ) ? 1000 : keepAliveTime );
681         pool.setBlockPolicy( blockPolicy );
682         pool.setShutdownGraceful( shutdownGraceful );
683         pool.setShutdownWaitTimeMs( shutdownWaitTime );
684
685         synchronized( m_pools )
686         {
687             m_pools.put( name, pool );
688         }
689
690         printPoolInfo( pool );
691         return pool;
692     }
693
694     /**
695      * DOCUMENT ME!
696      *
697      * @param pool DOCUMENT ME!
698      */

699     private void printPoolInfo( final DefaultThreadPool pool )
700     {
701         if( getLogger( ).isInfoEnabled( ) )
702         {
703             if( pool.isQueued( ) )
704             {
705                 final StringBuffer JavaDoc msg = new StringBuffer JavaDoc( );
706                 msg.append( "ThreadPool named \"" ).append( pool.getName( ) );
707                 msg.append( "\" created with maximum queue-size=" );
708                 msg.append( pool.getMaxQueueSize( ) );
709                 msg.append( ",max-pool-size=" ).append( pool.getMaximumPoolSize( ) );
710                 msg.append( ",min-pool-size=" ).append( pool.getMinimumPoolSize( ) );
711                 msg.append( ",priority=" ).append( pool.getPriority( ) );
712                 msg.append( ",isDaemon=" ).append( ( (ThreadFactory)pool.getThreadFactory( ) ).isDaemon( ) );
713                 msg.append( ",keep-alive-time-ms=" ).append( pool.getKeepAliveTime( ) );
714                 msg.append( ",block-policy=\"" ).append( pool.getBlockPolicy( ) );
715                 msg.append( "\",shutdown-wait-time-ms=" ).append( pool.getShutdownWaitTimeMs( ) );
716                 getLogger( ).info( msg.toString( ) );
717             }
718             else
719             {
720                 final StringBuffer JavaDoc msg = new StringBuffer JavaDoc( );
721                 msg.append( "ThreadPool named \"" ).append( pool.getName( ) );
722                 msg.append( "\" created with no queue,max-pool-size=" ).append( pool.getMaximumPoolSize( ) );
723                 msg.append( ",min-pool-size=" ).append( pool.getMinimumPoolSize( ) );
724                 msg.append( ",priority=" ).append( pool.getPriority( ) );
725                 msg.append( ",isDaemon=" ).append( ( (ThreadFactory)pool.getThreadFactory( ) ).isDaemon( ) );
726                 msg.append( ",keep-alive-time-ms=" ).append( pool.getKeepAliveTime( ) );
727                 msg.append( ",block-policy=" ).append( pool.getBlockPolicy( ) );
728                 msg.append( ",shutdown-wait-time-ms=" ).append( pool.getShutdownWaitTimeMs( ) );
729                 getLogger( ).info( msg.toString( ) );
730             }
731         }
732     }
733
734     //~ Inner Classes ----------------------------------------------------------
735

736     /**
737      * The $classType$ class ...
738      *
739      * @author <a HREF="mailto:giacomo.at.apache.org">Giacomo Pati</a>
740      * @version $Id: DefaultRunnableManager.java 56848 2004-11-07 14:09:23Z giacomo $
741      */

742     private class ExecutionInfo implements Comparable JavaDoc
743     {
744         //~ Instance fields ----------------------------------------------------
745

746         /** Our logger */
747         final Logger m_logger;
748
749         /** DOCUMENT ME! */
750         final Runnable JavaDoc m_command;
751
752         /** DOCUMENT ME! */
753         final ThreadPool m_pool;
754
755         /** DOCUMENT ME! */
756         final long m_delay;
757
758         /** DOCUMENT ME! */
759         final long m_interval;
760
761         /** DOCUMENT ME! */
762         long m_nextRun = 0;
763
764         //~ Constructors -------------------------------------------------------
765

766         /**
767          * Creates a new ExecutionInfo object.
768          *
769          * @param pool DOCUMENT ME!
770          * @param command DOCUMENT ME!
771          * @param delay DOCUMENT ME!
772          * @param interval DOCUMENT ME!
773          * @param logger DOCUMENT ME!
774          */

775         ExecutionInfo( final ThreadPool pool,
776                        final Runnable JavaDoc command,
777                        final long delay,
778                        final long interval,
779                        final Logger logger )
780         {
781             m_pool = pool;
782             m_command = command;
783             m_delay = delay;
784             m_interval = interval;
785             m_logger = logger;
786             m_nextRun = System.currentTimeMillis( ) + delay;
787
788             synchronized( m_commandStack )
789             {
790                 m_commandStack.add( this );
791                 m_commandStack.notifyAll( );
792             }
793             Thread.yield(); // Give others a chance to run
794
}
795
796         //~ Methods ------------------------------------------------------------
797

798         /**
799          * DOCUMENT ME!
800          *
801          * @param other DOCUMENT ME!
802          *
803          * @return DOCUMENT ME!
804          */

805         public int compareTo( final Object JavaDoc other )
806         {
807             final ExecutionInfo otherInfo = (ExecutionInfo)other;
808             int diff = (int)( m_nextRun - otherInfo.m_nextRun );
809             if (diff == 0) {
810                 if (this == other) {
811                     // Same object, return 0.
812
return 0;
813                 } else {
814                     // NOT the same object, MUST return non-0 value.
815
return System.identityHashCode(this) - System.identityHashCode(other);
816                 }
817             }
818             return diff;
819         }
820
821         /**
822          * DOCUMENT ME!
823          */

824         void execute( )
825         {
826             if( m_logger.isDebugEnabled( ) )
827             {
828                 m_logger.debug( "Executing command " + m_command + " in pool \"" +
829                                  m_pool.getName( ) + "\", schedule with interval=" + m_interval );
830             }
831
832             synchronized( m_commandStack )
833             {
834                 m_commandStack.remove( this );
835                 if( m_interval > 0 )
836                 {
837                     m_nextRun = System.currentTimeMillis( ) + m_interval;
838                     m_commandStack.add( this );
839                 }
840             }
841
842             try
843             {
844                 m_pool.execute( m_command );
845             }
846             catch( final InterruptedException JavaDoc ie )
847             {
848                 if( m_logger.isDebugEnabled( ) )
849                 {
850                     m_logger.debug( "Interrupted executing command + " + m_command );
851                 }
852             }
853             catch( final Throwable JavaDoc t )
854             {
855                 m_logger.error( "Exception executing command " + m_command, t );
856             }
857         }
858     }
859 }
860
Popular Tags