View Javadoc

1   /**********************************************************************
2    * ThreadPoolResizer.java
3    * created on 01.03.2005 by netseeker
4    * $Id: ThreadPoolResizer.java,v 1.5 2006/11/05 16:34:39 netseeker Exp $
5    * $Log: ThreadPoolResizer.java,v $
6    * Revision 1.5  2006/11/05 16:34:39  netseeker
7    * Code cleanup, added support of JDK 1.5  thread pools
8    *
9    * Revision 1.4  2006/08/10 18:57:06  netseeker
10   * *** empty log message ***
11   *
12   * Revision 1.3  2006/08/10 18:36:04  netseeker
13   * added abstraction of ThreadPools and an Executor based implementation for Java >= 1.5
14   *
15   * Revision 1.2  2006/08/09 20:13:54  netseeker
16   * *** empty log message ***
17   *
18   * Revision 1.1  2006/07/27 20:35:16  netseeker
19   * *** empty log message ***
20   *
21   *
22   * ====================================================================
23   *
24   *  Copyright 2005-2006 netseeker aka Michael Manske
25   *
26   *  Licensed under the Apache License, Version 2.0 (the "License");
27   *  you may not use this file except in compliance with the License.
28   *  You may obtain a copy of the License at
29   *
30   *      http://www.apache.org/licenses/LICENSE-2.0
31   *
32   *  Unless required by applicable law or agreed to in writing, software
33   *  distributed under the License is distributed on an "AS IS" BASIS,
34   *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
35   *  See the License for the specific language governing permissions and
36   *  limitations under the License.
37   * ====================================================================
38   *
39   * This file is part of the ejoe framework.
40   * For more information on the author, please see
41   * <http://www.manskes.de/>.
42   *
43   *********************************************************************/
44  package de.netseeker.ejoe.concurrent;
45  
46  import java.util.Timer;
47  import java.util.TimerTask;
48  
49  /***
50   * A controller thread which monitors a ThreadService and ensures that the limit of worker threads within the
51   * ThreadService will be adjusted according to the workload.
52   * 
53   * @author netseeker
54   * @since 0.3.9.1
55   */
56  public final class ThreadPoolResizer extends TimerTask
57  {
58      private ThreadService pool;
59  
60      private int           shrinkSize;
61  
62      private long          millisBeforeShrink = -1;
63  
64      private long          lastCheck          = -1;
65  
66      private int           maxPoolSize;
67  
68      /***
69       * Creates a new instance of ThreadPoolResizer, which can be scheduled via using a {@link Timer} and will monitor
70       * and eventually resize the given {@link ThreadService} up to the given limit of workers by checking the workload
71       * of the pool. If the workload is very high in all checks during the given period (millisBeforeShrink) the amount
72       * of workers in the monitored {@link ThreadService} will be increased to a calculated size between 1 and the given
73       * limit of workers. If the workload is too low the amount of workers will get reduced.
74       * 
75       * @param pool a {@link ThreadService} to monitor
76       * @param maxPoolSize the limit of worker threads for the {@link ThreadService}
77       * @param millisBeforeShrink the period before the {@link ThreadService} will get resized
78       */
79      public ThreadPoolResizer(ThreadService pool, int maxPoolSize, long millisBeforeShrink)
80      {
81          super();
82          this.pool = pool;
83          this.maxPoolSize = maxPoolSize;
84          this.millisBeforeShrink = millisBeforeShrink;
85      }
86  
87      /*
88       * (non-Javadoc)
89       * 
90       * @see java.util.TimerTask#run()
91       */
92      public void run()
93      {
94          long now = System.currentTimeMillis();
95          if ( this.lastCheck == -1 ) this.lastCheck = now;
96  
97          int current = pool.getCurrentPoolsize();
98          int active = pool.getActiveWorkerCount();
99  
100         boolean shrinkPossible = (current - active) > 0;
101 
102         if ( shrinkPossible )
103         {
104             if ( this.shrinkSize == 0 )
105                 this.shrinkSize = (active > 0) ? active : 1;
106             else
107                 this.shrinkSize = (int) Math.floor( (this.shrinkSize + active) / 2 );
108 
109             if ( (now - this.lastCheck) >= this.millisBeforeShrink )
110             {
111                 if ( this.shrinkSize > this.maxPoolSize )
112                 {
113                     this.shrinkSize = this.maxPoolSize;
114                 }
115 
116                 pool.resize( this.shrinkSize );
117             }
118         }
119         else
120             this.shrinkSize = 0;
121 
122         lastCheck = now;
123     }
124 }