1 16 package org.mortbay.util; 17 18 import java.io.Serializable ; 19 import java.util.HashMap ; 20 21 import org.apache.commons.logging.Log; 22 import org.mortbay.log.LogFactory; 23 24 25 31 public class Pool 32 implements LifeCycle, Serializable 33 { 34 private static Log log = LogFactory.getLog(Pool.class); 35 36 37 static int __max = 38 Integer.getInteger("POOL_MAX",256).intValue(); 39 static int __min = 40 Integer.getInteger("POOL_MIN",2).intValue(); 41 42 43 44 public static interface PondLife 45 { 46 int getID(); 47 void enterPool(Pool pool,int id); 48 void poolClosing(); 49 void leavePool(); 50 } 51 52 53 static HashMap __nameMap=new HashMap (); 54 55 56 private int _max = __max; 57 private int _min = __min; 58 private String _name; 59 private String _className; 60 private int _maxIdleTimeMs=10000; 61 private HashMap _attributes = new HashMap (); 62 63 private transient Class _class; 64 private transient PondLife[] _pondLife; private transient int[] _index; private transient int _size; 67 private transient int _available; 68 private transient int _running=0; 69 private transient long _lastShrink=0; 71 72 public static Pool getPool(String name) 73 { 74 return (Pool)__nameMap.get(name); 75 } 76 77 78 80 public Pool() 81 {} 82 83 84 87 public String getPoolName() 88 { 89 return _name; 90 } 91 92 93 97 public void setPoolName(String name) 98 throws IllegalStateException 99 { 100 synchronized(this) 101 { 102 synchronized(Pool.class) 103 { 104 if (_name!=null && !_name.equals(name)) 105 __nameMap.remove(_name); 106 if (__nameMap.containsKey(name)) 107 throw new IllegalStateException ("Name already exists"); 108 _name=name; 109 110 __nameMap.put(_name,this); 111 } 112 } 113 } 114 115 116 121 public void setPoolClass(Class poolClass) 122 throws IllegalStateException 123 { 124 synchronized(this) 125 { 126 if (_class!=poolClass) 127 { 128 if (_running>0) 129 throw new IllegalStateException ("Thread Pool Running"); 130 if (!PondLife.class.isAssignableFrom(poolClass)) 131 throw new IllegalArgumentException ("Not PondLife: "+poolClass); 132 _class=poolClass; 133 _className=_class.getName(); 134 } 135 } 136 } 137 138 139 140 public Class getPoolClass() 141 { 142 return _class; 143 } 144 145 146 public int getMinSize() 147 { 148 return _min; 149 } 150 151 152 public void setMinSize(int min) 153 { 154 _min=min; 155 } 156 157 158 public int getMaxSize() 159 { 160 return _max; 161 } 162 163 164 public void setMaxSize(int max) 165 { 166 _max=max; 167 } 168 169 170 public int getMaxIdleTimeMs() 171 { 172 return _maxIdleTimeMs; 173 } 174 175 176 public void setMaxIdleTimeMs(int maxIdleTimeMs) 177 { 178 _maxIdleTimeMs=maxIdleTimeMs; 179 } 180 181 182 public void setAttribute(String name,Object value) 183 { 184 _attributes.put(name,value); 185 } 186 187 188 public Object getAttribute(String name) 189 { 190 return _attributes.get(name); 191 } 192 193 194 public boolean isStarted() 195 { 196 return _running>0 && _pondLife!=null; 197 } 198 199 200 public int size() 201 { 202 return _size; 203 } 204 205 206 public int available() 207 { 208 return _available; 209 } 210 211 212 213 public void start() 214 throws Exception 215 { 216 synchronized(this) 217 { 218 _running++; 219 if (_running>1) 220 return; 221 222 if (_min >= _max || _max<1) 223 throw new IllegalStateException ("!(0<=min<max)"); 224 225 _pondLife=new PondLife[_max]; 227 _index=new int[_max]; 228 _size=0; 229 _available=0; 230 231 for (int i=0;i<_max;i++) 232 _index[i]=i; 233 for (int i=0;i<_min;i++) 234 newPondLife(); 235 } 236 } 237 238 239 public void stop() 240 throws InterruptedException 241 { 242 synchronized(this) 243 { 244 _running--; 245 if (_running>0) 246 return; 247 notifyAll(); 248 } 249 250 if (_pondLife!=null && _size>0) 251 { 252 for (int i=0;i<_pondLife.length;i++) 253 closePondLife(i); 254 Thread.yield(); 255 for (int i=0;i<_pondLife.length;i++) 256 stopPondLife(i); 257 } 258 259 synchronized(this) 260 { 261 _pondLife=null; 262 _index=null; 263 _size=0; 264 _available=0; 265 } 266 } 267 268 269 public PondLife get(int timeoutMs) 270 throws Exception 271 { 272 PondLife pl=null; 273 274 if (_available<_min) 276 Thread.yield(); 277 278 int new_id=-1; 279 280 synchronized(this) 282 { 283 if (_running>0 && _available==0 && _size==_pondLife.length && timeoutMs>0) 285 wait(timeoutMs); 286 287 if (_running>0) 289 { 290 if (_available>0) 292 { 293 int id=_index[--_available]; 294 pl=_pondLife[id]; 295 } 296 else if (_size<_pondLife.length) 297 { 298 new_id=reservePondLife(false); 300 } 301 } 302 303 if (pl==null && new_id>=0) 305 pl=newPondLife(new_id); 306 } 307 308 return pl; 309 } 310 311 312 313 public void put(PondLife pl) 314 throws InterruptedException 315 { 316 int id=pl.getID(); 317 318 synchronized(this) 319 { 320 if (_running==0) 321 stopPondLife(id); 322 else if (_pondLife[id]!=null) 323 { 324 _index[_available++]=id; 325 notify(); 326 } 327 } 328 329 } 330 331 332 public void shrink() 333 throws InterruptedException 334 { 335 if (_running==0) 336 return; 337 338 synchronized(this) 339 { 340 if (_maxIdleTimeMs>0) 342 { 343 long now=System.currentTimeMillis(); 344 if ((now-_lastShrink)<_maxIdleTimeMs) 345 return; _lastShrink=now; 347 } 348 349 if (_running>0 && _available>0 && _size>_min) 351 stopPondLife(_index[--_available]); 352 } 353 } 354 355 356 private int reservePondLife(boolean available) 357 throws Exception 358 { 359 int id=-1; 360 synchronized(this) 361 { 362 id=_index[_size++]; 363 if (available) 364 _index[_available++]=id; 365 } 366 return id; 367 } 368 369 370 private PondLife newPondLife(int id) 371 throws Exception 372 { 373 PondLife pl= (PondLife)_class.newInstance(); 374 _pondLife[id]=pl; 375 pl.enterPool(this,id); 376 return pl; 377 } 378 379 380 private PondLife newPondLife() 381 throws Exception 382 { 383 return newPondLife(reservePondLife(true)); 384 } 385 386 387 private void closePondLife(int id) 388 { 389 if (_pondLife[id]!=null) 390 _pondLife[id].poolClosing(); 391 } 392 393 394 private void stopPondLife(int id) 395 { 396 PondLife pl = null; 397 synchronized(this) 398 { 399 pl=_pondLife[id]; 400 if (pl!=null) 401 { 402 _pondLife[id]=null; 403 _index[--_size]=id; 404 if (_available>_size) 405 _available=_size; 406 } 407 } 408 if (pl!=null) 409 pl.leavePool(); 410 } 411 412 413 public void dump(String msg) 414 { 415 StringBuffer pond=new StringBuffer (); 416 StringBuffer avail=new StringBuffer (); 417 StringBuffer index=new StringBuffer (); 418 419 pond.append("pond: "); 420 avail.append("avail:"); 421 index.append("index:"); 422 423 for (int i=0;i<_pondLife.length;i++) 424 { 425 if (_pondLife[i]==null) 426 pond.append(" "); 427 else 428 { 429 pond.append(' '); 430 StringUtil.append(pond,(byte)i,16); 431 } 432 433 if (i==_size) 434 avail.append(i==_available?" AS":" S"); 435 else 436 avail.append(i==_available?" A ":" "); 437 438 index.append(' '); 439 StringUtil.append(index,(byte)_index[i],16); 440 } 441 442 System.err.println(); 443 System.err.println(msg); 444 System.err.println(pond); 445 System.err.println(avail); 446 System.err.println(index); 447 } 448 449 450 451 private void readObject(java.io.ObjectInputStream in) 452 throws java.io.IOException , ClassNotFoundException 453 { 454 in.defaultReadObject(); 455 if (_class==null || !_class.getName().equals(_className)) 456 { 457 try 458 { 459 setPoolClass(Loader.loadClass(Pool.class,_className)); 460 } 461 catch (Exception e) 462 { 463 log.warn(LogSupport.EXCEPTION,e); 464 throw new java.io.InvalidObjectException (e.toString()); 465 } 466 } 467 } 468 } 469 | Popular Tags |