KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > apache > excalibur > mpool > test > LatchedThreadGroup


1 /*
2  * Licensed to the Apache Software Foundation (ASF) under one or more
3  * contributor license agreements. See the NOTICE file distributed with
4  * this work for additional information regarding copyright ownership.
5  * The ASF licenses this file to You under the Apache License, Version 2.0
6  * (the "License"); you may not use this file except in compliance with
7  * the License. You 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.
15  *
16  * See the License for the specific language governing permissions and
17  * limitations under the License.
18  */

19 package org.apache.excalibur.mpool.test;
20
21 import org.apache.avalon.framework.logger.AbstractLogEnabled;
22 import org.apache.avalon.framework.logger.Logger;
23
24 /**
25  * This class is useful for writing MultiThreaded test cases where you need to perform
26  * multithreaded load testing on a component.
27  * <p>
28  * An instance of will create a block of threads of the specified size. Each thread will be
29  * assigned to run a specified Runnable instance. The threads will then all wait at a latch
30  * until the go method is called. The go method will not return until all of the
31  * Runnables have completed.
32  *
33  * @deprecated ECM is no longer supported
34  *
35  * @author <a HREF="mailto:dev@avalon.apache.org">Avalon Development Team</a>
36  * @version $Id: LatchedThreadGroup.java,v 1.1 2004/04/02 05:53:14 mcconnell Exp $
37  */

38 public class LatchedThreadGroup
39     extends AbstractLogEnabled
40 {
41     private Thread JavaDoc[] m_threads;
42     private Object JavaDoc m_semaphore = new Object JavaDoc();
43     private int m_startedCount;
44     private boolean m_latched;
45     private int m_completedCount;
46     private Throwable JavaDoc m_exception;
47
48     /*---------------------------------------------------------------
49      * Constructors
50      *-------------------------------------------------------------*/

51     /**
52      * Creates a LatchedThreadGroup with a thread for each Runnable in the runnables array.
53      */

54     public LatchedThreadGroup( Runnable JavaDoc[] runnables )
55     {
56         int threadCount = runnables.length;
57         m_threads = new Thread JavaDoc[ threadCount ];
58         for( int i = 0; i < threadCount; i++ )
59         {
60             m_threads[ i ] = new Runner( runnables[ i ], "Latched_Thread_" + i );
61         }
62     }
63
64     /**
65      * Creates a LatchedThreadGroup with threadCount threads each running runnable.
66      */

67     public LatchedThreadGroup( Runnable JavaDoc runnable, int threadCount )
68     {
69         m_threads = new Thread JavaDoc[ threadCount ];
70         for( int i = 0; i < threadCount; i++ )
71         {
72             m_threads[ i ] = new Runner( runnable, "Latched_Thread_" + i );
73         }
74     }
75
76     /*---------------------------------------------------------------
77      * Methods
78      *-------------------------------------------------------------*/

79     protected void resetMemory()
80     {
81         System.gc();
82         System.gc();
83
84         // Let the system settle down.
85
try
86         {
87             Thread.sleep( 50 );
88         }
89         catch( InterruptedException JavaDoc e )
90         {
91         }
92         Runtime JavaDoc runtime = Runtime.getRuntime();
93         getLogger().debug( "Memory: " + ( runtime.totalMemory() - runtime.freeMemory() ) );
94     }
95
96     /**
97      * Causes all of the Runnables to start at the same instance. This method will return
98      * once all of the Runnables have completed.
99      *
100      * @return time, in milliseconds, that it took for all of the Runnables to complete.
101      */

102     public long go()
103         throws Exception JavaDoc
104     {
105         // Start each of the threads. They will block until the latch is released. This is
106
// necessary because it takes some time for the threads to each allocate their required
107
// system resources and actually be ready to run.
108
int threadCount = m_threads.length;
109         for( int i = 0; i < threadCount; i++ )
110         {
111             m_threads[ i ].start();
112         }
113
114         // Wait for all of the threads to start before starting to time the test
115
synchronized( m_semaphore )
116         {
117             while( m_startedCount < threadCount )
118             {
119                 m_semaphore.wait();
120             }
121
122             // Start clean
123
resetMemory();
124
125             // Release the threads.
126
m_latched = true;
127             getLogger().debug( "Main thread released the test thread latch." );
128             m_semaphore.notifyAll();
129         }
130         // Start timing
131
long startTime = System.currentTimeMillis();
132
133         // Wait for all of the threads to complete
134
synchronized( m_semaphore )
135         {
136             getLogger().debug( "Waiting for test threads to all complete." );
137             while( m_completedCount < threadCount )
138             {
139                 try
140                 {
141                     m_semaphore.wait();
142                 }
143                 catch( InterruptedException JavaDoc e )
144                 {
145                 }
146             }
147         }
148         final long duration = System.currentTimeMillis() - startTime;
149         getLogger().debug( "All test threads completed." );
150
151         if( m_exception != null )
152         {
153             throw new CascadingAssertionFailedError( "Exception in test thread.", m_exception );
154         }
155         return duration;
156     }
157
158     /**
159      * Inner access method to getLogger() to work around a bug in the Javac compiler
160      * when getLogger() is called from the method of an inner class. Jikes seems to
161      * handle it Ok. :-/
162      */

163     private Logger getInnerLogger()
164     {
165         return getLogger();
166     }
167
168     /*---------------------------------------------------------------
169      * Inner Classes
170      *-------------------------------------------------------------*/

171     private class Runner extends Thread JavaDoc
172     {
173         private Runnable JavaDoc m_runnable;
174
175         protected Runner( Runnable JavaDoc runnable, String JavaDoc name )
176         {
177             super( name );
178             m_runnable = runnable;
179         }
180
181         public void run()
182         {
183             try
184             {
185                 // Need all threads to wait until all the others are ready.
186
synchronized( m_semaphore )
187                 {
188                     m_startedCount++;
189                     getInnerLogger().debug( "Started " + m_startedCount + " test threads." );
190                     if( m_startedCount >= m_threads.length )
191                     {
192                         m_semaphore.notifyAll();
193                     }
194                     while( !m_latched )
195                     {
196                         try
197                         {
198                             m_semaphore.wait();
199                         }
200                         catch( InterruptedException JavaDoc e )
201                         {
202                         }
203                     }
204                 }
205
206                 // Run the runnable
207
try
208                 {
209                     m_runnable.run();
210                 }
211                 catch( Throwable JavaDoc t )
212                 {
213                     synchronized( m_semaphore )
214                     {
215                         getInnerLogger().error( "Error in " + Thread.currentThread().getName(), t );
216                         if( m_exception != null )
217                         {
218                             m_exception = t;
219                         }
220                     }
221                 }
222             }
223             finally
224             {
225                 // Say that we are done
226
synchronized( m_semaphore )
227                 {
228                     m_completedCount++;
229                     getInnerLogger().debug( m_completedCount + " test threads completed." );
230                     m_semaphore.notifyAll();
231                 }
232             }
233         }
234     }
235 }
236
Popular Tags