View Javadoc

1   /*
2    * $Id: ThreadingProfile.java 9513 2007-10-31 14:16:22Z holger $
3    * --------------------------------------------------------------------------------------
4    * Copyright (c) MuleSource, Inc.  All rights reserved.  http://www.mulesource.com
5    *
6    * The software in this package is published under the terms of the CPAL v1.0
7    * license, a copy of which has been included with this distribution in the
8    * LICENSE.txt file.
9    */
10  
11  package org.mule.config;
12  
13  import org.mule.impl.work.MuleWorkManager;
14  import org.mule.umo.manager.UMOWorkManager;
15  import org.mule.util.MapUtils;
16  import org.mule.util.concurrent.NamedThreadFactory;
17  import org.mule.util.concurrent.WaitPolicy;
18  
19  import java.util.Map;
20  
21  import edu.emory.mathcs.backport.java.util.concurrent.BlockingQueue;
22  import edu.emory.mathcs.backport.java.util.concurrent.LinkedBlockingDeque;
23  import edu.emory.mathcs.backport.java.util.concurrent.RejectedExecutionHandler;
24  import edu.emory.mathcs.backport.java.util.concurrent.SynchronousQueue;
25  import edu.emory.mathcs.backport.java.util.concurrent.ThreadFactory;
26  import edu.emory.mathcs.backport.java.util.concurrent.ThreadPoolExecutor;
27  import edu.emory.mathcs.backport.java.util.concurrent.TimeUnit;
28  
29  import org.apache.commons.collections.map.CaseInsensitiveMap;
30  
31  /**
32   * <code>ThreadingProfile</code> is used to configure a thread pool. Mule uses a
33   * few different pools i.e. for component threads and message dispatchers. This object
34   * makes it easier to configure the pool.
35   */
36  
37  public class ThreadingProfile
38  {
39  
40      /**
41       * Default value for MAX_THREADS_ACTIVE
42       */
43      public static final int DEFAULT_MAX_THREADS_ACTIVE = 16;
44  
45      /**
46       * Default value for MAX_THREADS_IDLE
47       */
48      public static final int DEFAULT_MAX_THREADS_IDLE = 1;
49  
50      /**
51       * Default value for MAX_BUFFER_SIZE
52       */
53      public static final int DEFAULT_MAX_BUFFER_SIZE = 0;
54  
55      /**
56       * Default value for MAX_THREAD_TTL
57       */
58      public static final long DEFAULT_MAX_THREAD_TTL = 60000;
59  
60      /**
61       * Default value for DEFAULT_THREAD_WAIT_TIMEOUT
62       */
63      public static final long DEFAULT_THREAD_WAIT_TIMEOUT = 30000L;
64  
65      /**
66       * Default value for do threading
67       */
68      public static final boolean DEFAULT_DO_THREADING = true;
69  
70      /**
71       * Actions to perform on pool exhaustion
72       */
73      public static final int WHEN_EXHAUSTED_WAIT = 0;
74      public static final int WHEN_EXHAUSTED_DISCARD = 1;
75      public static final int WHEN_EXHAUSTED_DISCARD_OLDEST = 2;
76      public static final int WHEN_EXHAUSTED_ABORT = 3;
77      public static final int WHEN_EXHAUSTED_RUN = 4;
78  
79      /**
80       * Default action to perform on pool exhaustion
81       */
82      public static final int DEFAULT_POOL_EXHAUST_ACTION = WHEN_EXHAUSTED_RUN;
83  
84      // map pool exhaustion strings to their respective values
85      private static final Map POOL_EXHAUSTED_ACTIONS = new CaseInsensitiveMap()
86      {
87          private static final long serialVersionUID = 1L;
88  
89          // static initializer
90          {
91              Integer value = new Integer(WHEN_EXHAUSTED_WAIT);
92              this.put("WHEN_EXHAUSTED_WAIT", value);
93              this.put("WAIT", value);
94  
95              value = new Integer(WHEN_EXHAUSTED_DISCARD);
96              this.put("WHEN_EXHAUSTED_DISCARD", value);
97              this.put("DISCARD", value);
98  
99              value = new Integer(WHEN_EXHAUSTED_DISCARD_OLDEST);
100             this.put("WHEN_EXHAUSTED_DISCARD_OLDEST", value);
101             this.put("DISCARD_OLDEST", value);
102 
103             value = new Integer(WHEN_EXHAUSTED_ABORT);
104             this.put("WHEN_EXHAUSTED_ABORT", value);
105             this.put("ABORT", value);
106 
107             value = new Integer(WHEN_EXHAUSTED_RUN);
108             this.put("WHEN_EXHAUSTED_RUN", value);
109             this.put("RUN", value);
110         }
111     };
112 
113     private int maxThreadsActive = DEFAULT_MAX_THREADS_ACTIVE;
114     private int maxThreadsIdle = DEFAULT_MAX_THREADS_IDLE;
115     private int maxBufferSize = DEFAULT_MAX_BUFFER_SIZE;
116     private long threadTTL = DEFAULT_MAX_THREAD_TTL;
117     private long threadWaitTimeout = DEFAULT_THREAD_WAIT_TIMEOUT;
118     private int poolExhaustPolicy = DEFAULT_POOL_EXHAUST_ACTION;
119     private boolean doThreading = DEFAULT_DO_THREADING;
120 
121     private WorkManagerFactory workManagerFactory = new DefaultWorkManagerFactory();
122 
123     private RejectedExecutionHandler rejectedExecutionHandler;
124 
125     private ThreadFactory threadFactory;
126 
127     public ThreadingProfile()
128     {
129         super();
130     }
131 
132     public ThreadingProfile(int maxThreadsActive,
133                             int maxThreadsIdle,
134                             long threadTTL,
135                             int poolExhaustPolicy,
136                             RejectedExecutionHandler rejectedExecutionHandler,
137                             ThreadFactory threadFactory)
138     {
139         this.maxThreadsActive = maxThreadsActive;
140         this.maxThreadsIdle = maxThreadsIdle;
141         this.threadTTL = threadTTL;
142         this.poolExhaustPolicy = poolExhaustPolicy;
143         this.rejectedExecutionHandler = rejectedExecutionHandler;
144         this.threadFactory = threadFactory;
145     }
146 
147     public ThreadingProfile(ThreadingProfile tp)
148     {
149         this.maxThreadsActive = tp.getMaxThreadsActive();
150         this.maxThreadsIdle = tp.getMaxThreadsIdle();
151         this.maxBufferSize = tp.getMaxBufferSize();
152         this.threadTTL = tp.getThreadTTL();
153         this.threadWaitTimeout = tp.getThreadWaitTimeout();
154         this.poolExhaustPolicy = tp.getPoolExhaustedAction();
155         this.doThreading = tp.isDoThreading();
156         this.rejectedExecutionHandler = tp.getRejectedExecutionHandler();
157         this.threadFactory = tp.getThreadFactory();
158         this.workManagerFactory = tp.getWorkManagerFactory();
159     }
160 
161     public int getMaxThreadsActive()
162     {
163         return maxThreadsActive;
164     }
165 
166     public int getMaxThreadsIdle()
167     {
168         return maxThreadsIdle;
169     }
170 
171     public long getThreadTTL()
172     {
173         return threadTTL;
174     }
175 
176     public long getThreadWaitTimeout()
177     {
178         return threadWaitTimeout;
179     }
180 
181     public int getPoolExhaustedAction()
182     {
183         return poolExhaustPolicy;
184     }
185 
186     public RejectedExecutionHandler getRejectedExecutionHandler()
187     {
188         return rejectedExecutionHandler;
189     }
190 
191     public ThreadFactory getThreadFactory()
192     {
193         return threadFactory;
194     }
195 
196     public void setMaxThreadsActive(int maxThreadsActive)
197     {
198         this.maxThreadsActive = maxThreadsActive;
199     }
200 
201     public void setMaxThreadsIdle(int maxThreadsIdle)
202     {
203         this.maxThreadsIdle = maxThreadsIdle;
204     }
205 
206     public void setThreadTTL(long threadTTL)
207     {
208         this.threadTTL = threadTTL;
209     }
210 
211     public void setThreadWaitTimeout(long threadWaitTimeout)
212     {
213         this.threadWaitTimeout = threadWaitTimeout;
214     }
215 
216     public void setPoolExhaustedAction(int poolExhaustPolicy)
217     {
218         this.poolExhaustPolicy = poolExhaustPolicy;
219     }
220 
221     public void setPoolExhaustedActionString(String poolExhaustPolicy)
222     {
223         this.poolExhaustPolicy = MapUtils.getIntValue(POOL_EXHAUSTED_ACTIONS, poolExhaustPolicy,
224             DEFAULT_POOL_EXHAUST_ACTION);
225     }
226 
227     public void setRejectedExecutionHandler(RejectedExecutionHandler rejectedExecutionHandler)
228     {
229         this.rejectedExecutionHandler = rejectedExecutionHandler;
230     }
231 
232     public void setThreadFactory(ThreadFactory threadFactory)
233     {
234         this.threadFactory = threadFactory;
235     }
236 
237     public int getMaxBufferSize()
238     {
239         return maxBufferSize;
240     }
241 
242     public void setMaxBufferSize(int maxBufferSize)
243     {
244         this.maxBufferSize = maxBufferSize;
245     }
246 
247     public WorkManagerFactory getWorkManagerFactory()
248     {
249         return workManagerFactory;
250     }
251 
252     public void setWorkManagerFactory(WorkManagerFactory workManagerFactory)
253     {
254         this.workManagerFactory = workManagerFactory;
255     }
256 
257     public UMOWorkManager createWorkManager(String name)
258     {
259         return workManagerFactory.createWorkManager(this, name);
260     }
261 
262     public ThreadPoolExecutor createPool()
263     {
264         return createPool(null);
265     }
266 
267     public ThreadPoolExecutor createPool(String name)
268     {
269         BlockingQueue buffer;
270 
271         if (maxBufferSize > 0 && maxThreadsActive > 1)
272         {
273             buffer = new LinkedBlockingDeque(maxBufferSize);
274         }
275         else
276         {
277             buffer = new SynchronousQueue();
278         }
279 
280         if (maxThreadsIdle > maxThreadsActive)
281         {
282             maxThreadsIdle = maxThreadsActive;
283         }
284 
285         ThreadPoolExecutor pool = new ThreadPoolExecutor(maxThreadsIdle, maxThreadsActive, threadTTL,
286             TimeUnit.MILLISECONDS, buffer);
287 
288         // use a custom ThreadFactory if one has been configured
289         if (threadFactory != null)
290         {
291             pool.setThreadFactory(threadFactory);
292         }
293         else
294         {
295             // ..else create a "NamedThreadFactory" if a proper name was passed in
296             if (name != null)
297             {
298                 pool.setThreadFactory(new NamedThreadFactory(name)); 
299             }
300             else
301             {
302                 // let ThreadPoolExecutor create a default ThreadFactory;
303                 // see Executors.defaultThreadFactory()
304             }
305         }
306 
307         if (rejectedExecutionHandler != null)
308         {
309             pool.setRejectedExecutionHandler(rejectedExecutionHandler);
310         }
311         else
312         {
313             switch (poolExhaustPolicy)
314             {
315                 case WHEN_EXHAUSTED_DISCARD_OLDEST :
316                     pool.setRejectedExecutionHandler(new ThreadPoolExecutor.DiscardOldestPolicy());
317                     break;
318                 case WHEN_EXHAUSTED_RUN :
319                     pool.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());
320                     break;
321                 case WHEN_EXHAUSTED_ABORT :
322                     pool.setRejectedExecutionHandler(new ThreadPoolExecutor.AbortPolicy());
323                     break;
324                 case WHEN_EXHAUSTED_DISCARD :
325                     pool.setRejectedExecutionHandler(new ThreadPoolExecutor.DiscardPolicy());
326                     break;
327                 default :
328                     // WHEN_EXHAUSTED_WAIT
329                     pool.setRejectedExecutionHandler(new WaitPolicy(threadWaitTimeout, TimeUnit.MILLISECONDS));
330                     break;
331             }
332         }
333 
334         return pool;
335     }
336 
337     public boolean isDoThreading()
338     {
339         return doThreading;
340     }
341 
342     public void setDoThreading(boolean doThreading)
343     {
344         this.doThreading = doThreading;
345     }
346 
347     public String toString()
348     {
349         return "ThreadingProfile{" + "maxThreadsActive=" + maxThreadsActive + ", maxThreadsIdle="
350                         + maxThreadsIdle + ", maxBufferSize=" + maxBufferSize + ", threadTTL=" + threadTTL
351                         + ", poolExhaustPolicy=" + poolExhaustPolicy + ", threadWaitTimeout="
352                         + threadWaitTimeout + ", doThreading=" + doThreading + ", workManagerFactory="
353                         + workManagerFactory + ", rejectedExecutionHandler=" + rejectedExecutionHandler
354                         + ", threadFactory=" + threadFactory + "}";
355     }
356 
357     public static interface WorkManagerFactory
358     {
359         UMOWorkManager createWorkManager(ThreadingProfile profile, String name);
360     }
361 
362     private class DefaultWorkManagerFactory implements WorkManagerFactory
363     {
364         public UMOWorkManager createWorkManager(ThreadingProfile profile, String name)
365         {
366             return new MuleWorkManager(profile, name);
367         }
368     }
369 
370 }