001 /* 002 * Copyright (c) 2009 The openGion Project. 003 * 004 * Licensed under the Apache License, Version 2.0 (the "License"); 005 * you may not use this file except in compliance with the License. 006 * You may obtain a copy of the License at 007 * 008 * http://www.apache.org/licenses/LICENSE-2.0 009 * 010 * Unless required by applicable law or agreed to in writing, software 011 * distributed under the License is distributed on an "AS IS" BASIS, 012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, 013 * either express or implied. See the License for the specific language 014 * governing permissions and limitations under the License. 015 */ 016 package org.opengion.fukurou.util; 017 018 import java.util.MissingResourceException; 019 import java.util.Map; 020 import java.util.HashMap; 021 // import java.util.Date; 022 import java.util.List; 023 import java.util.ArrayList; 024 import java.util.Iterator; 025 // import java.util.Locale ; 026 027 // import java.text.DateFormat; 028 // import java.text.SimpleDateFormat; 029 030 /** 031 * AbstractObjectPool は、生成された Object を?ールするキャ?ュクラスです? 032 * サブクラスで、各クラスごとにオブジェクトを生???期化?終?るよ??ソ?? 033 * コー?ングしなおしてください? 034 * サブクラスでは、Object createInstance() と、oid objectInitial( Object obj )? 035 * void objectFinal( Object obj ) ?オーバ?ライドしてください? 036 * 037 * @version 4.0 038 * @author Kazuhiko Hasegawa 039 * @since JDK5.0, 040 */ 041 abstract public class AbstractObjectPool<E> { 042 /** ?でオブジェクトをプ?ルして?配?? */ 043 private List<E> pool = null; // プ?ルして?オブジェク? 044 private Map<Integer,TimeStampObject> poolBack = null; // 作?したオブジェクト?タイ?タンプ管? 045 046 /** プ?ル自体を拡張可能かど?を決める変数。拡張制?true)?無制?false) */ 047 private boolean limit ; 048 049 /** ?オブジェクト数 */ 050 private int maxsize ; 051 052 /** 生?したオブジェクト?寿命(?を指定します? 0 は、制限なしです?*/ 053 private int limitTime ; // 3.5.4.3 (2004/01/05) キャ?ュの寿命を指定します? 054 055 /** 制限なし?場合でも?実質こ?値以上?キャ?ュは、許可しません?/ 056 private static final int MAX_LIMIT_COUNT = 1000 ; // 3.6.0.8 (2004/11/19) 057 058 /** 059 * 初期化メソ? 060 * 061 * 初期オブジェクト数、最大オブジェクト数、拡張制限を?します? 062 * 063 * 初期オブジェクト数は、?ールを作?すると同時に確保するオブジェクト?個数です? 064 * オブジェクト?生?に時間がかかり、かつ、??使用するのであれば, 065 * 予め?確保しておけば、パフォーマンスが向上します? 066 * ?オブジェクト数は、拡張制限が、無制?limit = false )の場合?? 067 * 無視されます?制限あり?場合?、この値を上限に、オブジェクトを増やします? 068 * 拡張制限?、生成するオブジェクト数に制限をかけるかど?を指定します? 069 * ?に、コネクション等?リソースを確保する?合?、拡張制限を?て? 070 * 生?するオブジェクト数を制限します? 071 * 072 * @param minsize 初期オブジェクト数 073 * @param maxsize ?オブジェクト数 074 * @param limit 拡張制?true)?無制?false) 075 */ 076 protected synchronized void init( final int minsize, final int maxsize, final boolean limit ) { 077 init( minsize, maxsize, limit,0 ) ; 078 } 079 080 /** 081 * 初期化メソ? 082 * 083 * 初期オブジェクト数、?期?列数、拡張制限?オブジェクト?寿命を指定します? 084 * 085 * 初期オブジェクト数、?期?列数、拡張制限?までは、{@link #init( int , int , boolean ) init} 086 * を参照してください? 087 * オブジェクト?寿命は、生成された時間からの経過時間(??、キャ?ュしておく 088 * 場合に使用します? 089 * 例えば、コネクション等で?期間のプ?リングがリソースを圧迫する場合や? 090 * 接続?自身が?タイマ?で?する場合など、オブジェクト?生存期間を 091 * ?して管?る?があります? 092 * 093 * @param minsize 初期オブジェクト数 094 * @param maxsize 初期配?数 095 * @param limit 拡張制?true)?無制?false) 096 * @param limitTime オブジェクト?寿命の時間制限?(? 097 * @see #init( int , int , boolean ) 098 */ 099 protected synchronized void init( final int minsize, final int maxsize, 100 final boolean limit,final int limitTime ) { 101 pool = new ArrayList<E>( maxsize ); 102 poolBack = new HashMap<Integer,TimeStampObject>(); 103 this.maxsize = maxsize; 104 this.limit = limit; 105 this.limitTime = limitTime; 106 for( int i=0; i<minsize; i++ ) { 107 E obj = createInstance(); 108 pool.add( obj ); 109 110 Integer key = Integer.valueOf( obj.hashCode() ); 111 poolBack.put( key,new TimeStampObject( obj,limitTime ) ); 112 } 113 } 114 115 /** 116 * キャ?ュのインスタンスを返します? 117 * 118 * なお?拡張制限をして?場合に、最初に確保した数以上?オブジェクト生成? 119 * 要求があった?合?? MissingResourceException ?throw されます? 120 * ま?オブジェクトが寿命を?て?場合?、削除した後?新たに次の 121 * オブジェクト?生?を行います? 122 * 123 * @og.rev 4.0.0.1 (2007/12/03) 生?リミットチェ?を厳?行う? 124 * @og.rev 4.0.0.1 (2007/12/03) 生?リミットエラー時に、タイ?ウトをチェ?する? 125 * 126 * @return キャ?ュのインスタンス 127 * @throws MissingResourceException 拡張制限により、新しいインスタンスを生成できな??? 128 */ 129 public synchronized E newInstance() throws MissingResourceException { 130 final E rtnobj ; 131 if( pool.isEmpty() ) { 132 if( limit && poolBack.size() >= maxsize ) { 133 String errMsg = "生?リミットいっぱ?新たに生?できません?" 134 + poolBack.size() + "]"; 135 136 // 4.0.0.1 (2007/12/03) 生?リミットエラー時に、タイ?ウトをチェ?する? 137 Iterator<TimeStampObject> itr = poolBack.values().iterator(); 138 while( itr.hasNext() ) { 139 TimeStampObject tso = itr.next(); 140 if( tso == null || tso.isTimeOver() ) { 141 itr.remove(); 142 } 143 } 144 145 throw new MissingResourceException( errMsg,getClass().getName(),"limit" ); 146 } 147 else if( poolBack.size() > MAX_LIMIT_COUNT ) { 148 clear(); // 全件キャ?ュを??ます? 149 String errMsg = "ObjectPool で、メモリリークの可能性があります?[" 150 + poolBack.size() + "]"; 151 throw new RuntimeException( errMsg ); 152 } 153 // 新規作? 154 rtnobj = createInstance(); 155 Integer key = Integer.valueOf( rtnobj.hashCode() ); 156 poolBack.put( key,new TimeStampObject( rtnobj,limitTime ) ); 157 } 158 else { 159 // 既存取り?? 160 rtnobj = pool.remove(0); 161 if( rtnobj != null ) { 162 Integer key = Integer.valueOf( rtnobj.hashCode() ); 163 TimeStampObject tso = poolBack.get( key ); 164 if( tso == null || tso.isTimeOver() ) { 165 remove( rtnobj ); 166 return newInstance(); 167 } 168 } 169 else { 170 // 通常ありえな?? 171 String errMsg = "オブジェクト?取得に失敗しました? ; 172 throw new MissingResourceException( errMsg,getClass().getName(),"pool" ); 173 } 174 } 175 176 return rtnobj; 177 } 178 179 /** 180 * 具体的に新しいインスタンスを生成するメソ?? 181 * 182 * サブクラスで具体的に記述する?があります? 183 * 184 * @return 新しいインスタンス 185 */ 186 abstract protected E createInstance(); 187 188 /** 189 * オブジェクトを、オブジェクト?ールに戻します? 190 * 戻すべきオブジェクトが null の場合?,削除されたと判断します? 191 * 192 * @param obj オブジェクト?ールに戻すオブジェク? 193 */ 194 public synchronized void release( final E obj ) { 195 E obj2 = objectInitial( obj ); 196 if( obj2 != null ) { 197 Integer key = Integer.valueOf( obj2.hashCode() ); 198 TimeStampObject tso = poolBack.get( key ); 199 if( tso != null ) { 200 pool.add( obj2 ); 201 } 202 else { // 3.5.6.2 (2004/07/05) 追? 203 LogWriter.log( "ObjectPool で、メモリリークの可能性がある?[" + obj2 + "]" ); 204 remove( obj2 ); 205 } 206 } 207 } 208 209 /** 210 * オブジェクトを、オブジェクト?ールから削除します? 211 * remove されるオブジェクト?、すでにキャ?ュから取り出された後なので? 212 * そ?まま、何もしなければ自然消?GC)されます? 213 * 自然消?る前に、objectFinal( Object ) が呼ばれます? 214 * 生?されたオブジェクト?総数も?ひとつ減らします? 215 * 216 * @param obj 削除するオブジェク? 217 */ 218 public synchronized void remove( final E obj ) { 219 if( obj != null ) { 220 Integer key = Integer.valueOf( obj.hashCode() ); 221 poolBack.remove( key ); 222 } 223 224 objectFinal( obj ); 225 } 226 227 /** 228 * オブジェクト?ールの要?を返します? 229 * 230 * @return プ?ルの要? 231 */ 232 public synchronized int size() { 233 return poolBack.size(); 234 } 235 236 /** 237 * オブジェクト?ールが要?持たな?ど?を判定します? 238 * 239 * @return オブジェクト?ールが要?持って???つまりそのサイズ?0 の場合に? true、そ?な??合? false 240 */ 241 public synchronized boolean isEmpty() { 242 return poolBack.isEmpty() ; 243 } 244 245 /** 246 * すべての要? オブジェクト?ールから削除します? 247 * 貸し?し中のオブジェクト?、クリアしません。よって、返り値は? 248 * すべてのオブジェクトをクリアできた場合?、true 、貸し?し中の 249 * オブジェクトが存在した場?クリアできなかった??は、false です? 250 * 251 * @return すべてクリア(true)/貸し?し中のオブジェクトが残って?(false) 252 */ 253 public synchronized boolean clear() { 254 Iterator<E> itr = pool.iterator(); 255 while( itr.hasNext() ) { 256 remove( itr.next() ); 257 } 258 pool.clear(); 259 260 // 貸し?し中の場合?、remove 出来な?、poolBack に残って?? 261 // それでも?poolBack をクリアすることで、release 返却時にも? 262 // remove されるよ?なります? 263 // ただし?作?オブジェクト数が?? 0 にリセ?される為? 264 // ?貸し?し可能数が???増えてしま?す? 265 boolean flag = poolBack.isEmpty(); 266 poolBack.clear(); 267 268 return flag; 269 } 270 271 /** 272 * オブジェクト?ールから削除するときに呼ばれます? 273 * こ?メソ?で?ブジェクトごとの終???行います? 274 * 例えば???タベ?スコネクションであれば?close() 処?どです? 275 * 276 * ?ォルトでは、なにも行いません? 277 * 278 * @param obj 終???行うオブジェク? 279 */ 280 protected synchronized void objectFinal( final E obj ) { 281 // ここでは処?行いません? 282 } 283 284 /** 285 * オブジェクト?ールに戻すと?release すると?に呼ばれます? 286 * こ?メソ?で?ブジェクトごとの初期処?行います? 287 * オブジェクト?ールに戻すときには?初期化して?次の貸し?しに 288 * 対応できるように、?期??ておく?があります? 289 * 290 * ?ォルトでは、引数のオブジェクトをそ?まま返します? 291 * 292 * @param obj 初期処?行うオブジェク? 293 * 294 * @return 初期処?行ったオブジェク? 295 */ 296 protected synchronized E objectInitial( final E obj ) { 297 return obj; 298 } 299 300 /** 301 * ?状況を簡易的に表現した??を返します? 302 * 303 * @return こ?オブジェクト?ールの??表現 304 */ 305 @Override 306 public synchronized String toString() { 307 StringBuilder buf = new StringBuilder(); 308 buf.append( " freeCount = [" ).append( pool.size() ).append( "]\n" ); 309 buf.append( " createCount = [" ).append( poolBack.size() ).append( "]" ); 310 buf.append( " ( max=[" ).append( maxsize ).append( "] )\n" ); 311 buf.append( " limiter = [" ).append( limit ).append( "]\n" ); 312 buf.append( " limitTime = [" ).append( limitTime ).append( "](s)\n" ); 313 314 Iterator<E> itr = pool.iterator(); 315 buf.append( "Free Objects \n" ); 316 while( itr.hasNext() ) { 317 E obj = itr.next(); 318 if( obj != null ) { 319 Integer key = Integer.valueOf( obj.hashCode() ); 320 buf.append( " " ); 321 buf.append( poolBack.get( key ) ); 322 buf.append( " " ).append( obj ); 323 buf.append( "\n" ); 324 } 325 } 326 return buf.toString(); 327 } 328 } 329 330 /** 331 * TimeStampObject は、生成された Object を?生?時刻とともに管?るクラスです? 332 * ?のハッシュキーは、登録するオブジェクトと同?、管?きるのは、異なるオブジェク? 333 * のみです? 334 * 335 * @version 4.0 336 * @author Kazuhiko Hasegawa 337 * @since JDK5.0, 338 */ 339 class TimeStampObject implements Comparable<TimeStampObject> { // 4.3.3.6 (2008/11/15) Generics警告対? 340 private final long timeStamp ; 341 private final long limitTime ; 342 private final int hcode ; 343 344 /** 345 * コンストラクター? 346 * 347 * @param obj 管?るオブジェク? 348 * @param limit オブジェクト?寿命(? 349 * @throws IllegalArgumentException TimeStampObject のインスタンスに、NULL はセ?できません? 350 */ 351 public TimeStampObject( final Object obj,final int limit ) { 352 if( obj == null ) { 353 String errMsg = "TimeStampObject のインスタンスに、NULL はセ?できません? ; 354 throw new IllegalArgumentException( errMsg ); 355 } 356 357 timeStamp = System.currentTimeMillis(); 358 if( limit > 0 ) { 359 limitTime = timeStamp + limit * 1000L ; 360 } 361 else { 362 limitTime = Long.MAX_VALUE ; 363 } 364 365 hcode = (int)((timeStamp)&(Integer.MAX_VALUE))^(obj.hashCode()) ; 366 } 367 368 /** 369 * ?管?て?オブジェクト?生?時刻を返します? 370 * 371 * @return 生?時刻(ms) 372 */ 373 public long getTimeStamp() { 374 return timeStamp; 375 } 376 377 /** 378 * オブジェクト?寿命がきたかど?を返します? 379 * 380 * @return 寿命判?true:寿命/false:ま?える) 381 */ 382 public boolean isTimeOver() { 383 return (System.currentTimeMillis() > limitTime ); 384 } 385 386 /** 387 * オブジェクトが同じかど?を判定します? 388 * 389 * ?オブジェクト? equals() メソ?と、作?時刻の両方を判断します? 390 * ?オブジェクト? equals() が同じでも?作?時刻が異なると? 391 * false を返します?これは、?く同?ブジェクトを管?る?合でも? 392 * タイ?タンプを差し替える事で、異なるオブジェクトとして 393 * 認識させると?ことです? 394 * 395 * @param obj Object 396 * 397 * @return true:同じ/false:異なる? 398 */ 399 public boolean equals( final Object obj ) { 400 if( obj instanceof TimeStampObject ) { 401 TimeStampObject other = (TimeStampObject)obj ; 402 return ( hcode == other.hcode ) && ( timeStamp == other.timeStamp ) ; 403 } 404 return false ; 405 } 406 407 /** 408 * ハッシュコードを返します? 409 * 410 * ここで返すのは、???身のハッシュコードではなく? 411 * ?管??オブジェクト?ハッシュコードです? 412 * 413 * hashcode = (int)((timeStamp)&(Integer.MAX_VALUE))^(obj.hashCode()) 414 * 415 * こ?計算式?、変更される可能性があります? 416 * 417 * @return ?管??オブジェクト?ハッシュコー? 418 */ 419 public int hashCode() { return hcode; } 420 421 /** 422 * こ?オブジェクトと?されたオブジェクト??を比?ます? 423 * 424 * こ?オブジェクトが?されたオブジェクトより小さ??合???整数? 425 * 等し??合?ゼロ、大きい場合?正の整数を返します? 426 * 427 * @param other TimeStampObject オブジェク? 428 * 429 * @return ?比??値 430 * @throws ClassCastException ?されたオブジェクトがキャストできな??合? 431 * @see Comparable#compareTo(Object) 432 */ 433 // public int compareTo( final Object obj ) { 434 public int compareTo( final TimeStampObject other ) { // 4.3.3.6 (2008/11/15) Generics警告対? 435 // TimeStampObject other = (TimeStampObject)obj; 436 long diff = (timeStamp - other.timeStamp); 437 438 if( diff > 0 ) { return 1; } 439 else if( diff < 0 ) { return -1; } 440 else { 441 if( equals( other ) ) { return 0; } 442 else { return (hcode - other.hcode); } 443 } 444 } 445 446 /** 447 * こ?オブジェクト??表現を返します? 448 * 449 * @og.rev 5.5.7.2 (2012/10/09) HybsDateUtil を利用するように修正します? 450 * 451 * @return オブジェクト??表現?? 452 */ 453 public String toString() { 454 // Create Timeは、?求めれ?変わらな??で、キャ?ュしても良?? 455 // DateFormat formatter = new SimpleDateFormat( "yyyy/MM/dd HH:mm:ss",Locale.JAPAN ); 456 457 // return ( "[Create Time = " + formatter.format( new Date( timeStamp ) ) 458 // + " , Time Over = " + (int)((limitTime - System.currentTimeMillis())/1000.0) + "(S)]" ); 459 460 return ( "[Create Time = " + HybsDateUtil.getDate( timeStamp,"yyyy/MM/dd HH:mm:ss" ) 461 + " , Time Over = " + (int)((limitTime - System.currentTimeMillis())/1000.0) + "(S)]" ); 462 } 463 }