/* ==================================================================
* Created [2009-4-27 下午11:32:55] by Jon.King
* ==================================================================
* TSS
* ==================================================================
* mailTo:jinpujun@hotmail.com
* Copyright (c) Jon.King, 2009-2012
* ==================================================================
*/
package com.jinhe.tss.core.cachepool;
import com.jinhe.tss.core.cachepool.container.ContainerFactory;
import com.jinhe.tss.core.cachepool.container.IPoolContainer;
import com.jinhe.tss.core.exception.BusinessException;
import com.jinhe.tss.core.util.BeanUtil;
/**
* <p> ObjectPool.java </p>
*
* 缓存对象池
*
* @author Jon.King 2006-12-28
*/
public class ObjectPool extends AbstractPool implements ICleaner{
// 对象池属性
private IPoolContainer free; // 空闲的对象池
private IPoolContainer using; // 使用中的对象池
private static int cleanerCount = 0;
private Cleaner cleaner; //清理器
private InitThread initer;
public ObjectPool(){
}
/**
* 初始化指定数量的对象放入池中。
* 本方法将产生一个新的线程来初始化这些对象。
* 本方法跟release()方法是相对立的。
* @param num
*/
public final void init() {
released = false;
Class<?> collectionType = BeanUtil.createClassByName(getCacheStrategy().getPoolCollectionClass());
if (!IPoolContainer.class.isAssignableFrom(collectionType))
throw new BusinessException("指定的池集合类类型非法: " + collectionType.getName()
+ " (必须实现cachepool.container.IPoolContainer接口)");
ContainerFactory factory = ContainerFactory.getInstance();
free = free != null? free : factory.create(collectionType.getName(), getCacheStrategy().getCode() + "_free");
using = using != null? using : factory.create(collectionType.getName(), getCacheStrategy().getCode() + "_using");
addObjectPoolListener(new ObjectPoolListener()); //为缓存池添加一个监听器
startInitThread(getCacheStrategy().getInitNum().intValue());
initCleaner();
log.info("缓存池(" + strategy.getName() + ")初始化成功!");
}
/**
* 启动初始化线程
* @param num
*/
void startInitThread(int num){
if (num == 0)
return;
int maxSize = getCacheStrategy().getPoolSize().intValue();
if (num > 0 && (maxSize == 0 || num <= maxSize)) {
shutDownIniter();
(initer = new InitThread(num)).start();
} else
throw new IllegalArgumentException("初始化缓冲池的num参数非法");
}
/**
* 创建检查间隔最少为5秒的清除线程。
* 本方法包级私有
*/
public void initCleaner(){
shutDownCleaner();
if (strategy.getCyclelife().longValue() > 0){
long cyclelife = strategy.getCyclelife().longValue();
long iVal = cyclelife == 0 ? 1000*60*60*24 : Math.max(1000*5, cyclelife / 5);
(cleaner = new Cleaner(this, iVal)).start();
}
}
/**
* 销毁 cleaner, initer 线程
*/
private void shutDownCleaner() {
if (cleaner != null) {
cleaner.halt();
try {
cleaner.join(); //等待线程死亡
} catch (InterruptedException e) {
log.error("停止旧的cleaner线程时被中断", e);
}
cleaner = null;
}
}
private void shutDownIniter() {
if (initer != null){
initer.halt();
try {
initer.join(); //等待线程死亡
} catch (InterruptedException e) {
log.error("停止initer线程时被中断", e);
}
initer = null;
}
}
public final void release(boolean forced) {
if (released) return;
released = true;
shutDownCleaner();
shutDownIniter();
synchronized (this) {
int rel = 0, failed = 0;
// 销毁所有的缓存项(包括尚在使用中的)
if (forced) {
for (CacheableKey key : using.getKeys()) {
try {
destroyObject(free.get(key));
rel++;
} catch (Exception e) {
failed++;
log.error("无法释放池中的缓存项目", e);
}
}
using.clear();
} else {
if (using.size() > 0) log.info("等待<使用中的>缓存项 被 check in pool...");
while (using.size() > 0) {
try {
wait(); // 等待,当连接被checkIn回来时,监听器会调用pool的notifyAll()通知这里
} catch (InterruptedException e) {
}
}
}
// 销毁当前所有空闲状态的缓存项
for (CacheableKey key : free.getKeys()) {
try {
destroyObject(free.get(key));
rel++;
} catch (Exception e) {
failed++;
log.error("无法释放池中的缓存项目", e);
}
}
free.clear();
String s = "成功释放 " + rel + " 个缓存项";
if (failed > 0) {
s += " (有 " + failed + " 个缓存项释放失败)";
}
log.info(s);
firePoolEvent(ObjectPoolEvent.POOL_RELEASED);
listeners.clear();
}
}
/**
* 线程执行清除池中过期的对象。
* 当对象尚在使用中,线程将会等待对象返回。对象返回时将触发线程再次执行清除。
*/
private final class Cleaner extends Thread {
private ObjectPool pool;
private long interval; // 定期清除缓存池时间间隔
private boolean stopped; // 缓存Cleaner是否已经被挂起
Cleaner(ObjectPool pool, long interval) {
this.setName("CleanerThread_" + Integer.toString(cleanerCount++)); // 设置线程名称
this.pool = pool;
this.interval = interval;
}
public void start() {
stopped = false;
super.start();
}
/**
* 安全的停止线程的运行,将线程挂起
*/
public void halt() {
if (!isHalted()) {
stopped = true;
interrupt(); // 必要的时间再将线程唤醒
}
}
/**
* 返回线程的状态,是否被挂起
*/
public boolean isHalted() {
return stopped;
}
/**
* 处理过期的对象
*/
public void run() {
while (pool.cleaner == Thread.currentThread() && !stopped) {
try {
if (!stopped) {
sleep(interval);
}
synchronized (pool) {
if (!pool.purge()) {
pool.wait(); //使本cleaner线程进入等待休眠状态。(线程进入该对象的休息室waitSet)
//当pool池的checkIn或者putIn事件被触发时,唤醒本cleaner线程
}
}
} catch (InterruptedException e) {
log.debug("运行cleaner线程时出错!", e);
}
}
}
}
/**
* 线程执行初始化池中对象。
*/
private final class InitThread extends Thread{
private int num;
private boolean stopped = false;
private InitThread(int num){
this.num = Math.min(getCacheStrategy().getPoolSize().intValue(), Math.max(num, 0)); // Ensure 0 < num < poolSize.
}
public void halt() { stopped = true; }
/**
* 生成指定数量的缓存对象。如果池中已有对象存在且数量小于指定数目,则线程将补足不足的对象数目。
*/
public void run(){
while ( getSize() < num ){
if(stopped){
log.debug("初始化线程已经停止!");
return;
}
try{
Cacheable o = arithmetic.create(getCacheStrategy().getCyclelife());
if (o == null){
String errorMsg = ObjectPool.this.getName() + "池初始化时无法创建对象";
log.error(errorMsg);
throw new BusinessException(errorMsg);
}else{
putObject(o.getKey(), o.getValue());
}
}catch (Exception e){
log.error("无法在池中初始化对象", e);
stopped = true; //如果本次循环创建对象失败,则将线程标记设置为停用,下次循环判断的时候即可推出循环,以免进入死循环。
}
}
log.debug(ObjectPool.this.getName() + "池中初始化了 " + getSize() + " 个新的对象");
}
}
public IPoolContainer getFree() { return free; }
public IPoolContainer getUsing() { return using; }
public final synchronized int getSize() {
return (free == null ? 0 : free.size()) + (using == null ? 0 : using.size());
}
}