概念
对象池(ObjectPool): 掌管对象的生命周期,获取,激活,验证,钝化,销毁等
池对象(PooledObject): 被创建在池中的对象,自己可以有一些附加信息
池对象工厂(PooledObjectFactory): 池中对象各个生命周期的具体实现,怎么创建,怎么验证,怎么销毁。
对象池化主要用于减少对象在创建和销毁上面的开销,如果是小对象则不需要池化,如果是大对象可以考虑池化,对于像数据库连接、网络之类的重对象来说是很有必要池化的,开发者自己根据需求判断,如果创建某种对象成为了影响程序性能的关键因素则需要池化。
使用commons-pool2
maven引入:
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-pool2</artifactId>
<version>2.4.2</version>
</dependency>
2. 结合thrift创建连接池:
首先需要一个池对象工厂,继承BasePooledObjectFactory
import java.net.Socket;
import org.apache.commons.pool2.BasePooledObjectFactory;
import org.apache.commons.pool2.PooledObject;
import org.apache.commons.pool2.impl.DefaultPooledObject;
import org.apache.thrift.transport.TSocket;
/**
* TSocket池对象工厂,只使用了部分需要的方法
*
* @author gqliu 2015年10月15日
*
*/
public class TSocketFactory extends BasePooledObjectFactory<TSocket> {
private String ip;
private int port;
public TSocketFactory(String ip, int port) {
this.ip = ip;
this.port = port;
}
/**
* 创建对象
*/
@Override
public TSocket create() throws Exception {
TSocket socket = new TSocket(ip, port);
socket.open();
return socket;
}
/**
* 用PooledObject封装对象放入池中
*/
@Override
public PooledObject<TSocket> wrap(TSocket socket) {
return new DefaultPooledObject<TSocket>(socket);
}
/**
* 销毁对象
*/
@Override
public void destroyObject(PooledObject<TSocket> p) throws Exception {
TSocket socket = p.getObject();
socket.close();
super.destroyObject(p);
}
/**
* 验证对象
*/
@Override
public boolean validateObject(PooledObject<TSocket> p) {
TSocket t = p.getObject();
Socket s = t.getSocket();
boolean closed = s.isClosed();
boolean connected = s.isConnected();
boolean outputShutdown = s.isOutputShutdown();
boolean inputShutdown = s.isInputShutdown();
boolean urgentFlag = false;
try {
s.sendUrgentData(0xFF);
urgentFlag = true;
} catch (Exception e) {
}
return urgentFlag && connected && !closed && !inputShutdown && !outputShutdown;
}
}
使用GenericObjectPool封装一个连接池:
import java.io.InputStream;
import java.util.Properties;
import org.apache.commons.pool2.impl.GenericObjectPool;
import org.apache.commons.pool2.impl.GenericObjectPoolConfig;
import org.apache.thrift.transport.TSocket;
/**
* 连接池
* @author gqliu
* 2015年11月7日
*
*/
public class TSocketPool {
private GenericObjectPool<TSocket> socketPool;
public TSocketPool(InputStream in) {
Properties pro = new Properties();
try {
pro.load(in);
} catch (Exception e) {
e.printStackTrace();
System.exit(-1);
}
// 初始化对象池配置
GenericObjectPoolConfig poolConfig = new GenericObjectPoolConfig();
poolConfig.setBlockWhenExhausted(Boolean.parseBoolean(pro.getProperty("thrift_blockWhenExhausted")));
poolConfig.setMaxWaitMillis(Long.parseLong(pro.getProperty("thrift_maxWait")));
poolConfig.setMinIdle(Integer.parseInt(pro.getProperty("thrift_minIdle")));
poolConfig.setMaxIdle(Integer.parseInt(pro.getProperty("thrift_maxIdle")));
poolConfig.setMaxTotal(Integer.parseInt(pro.getProperty("thrift_maxTotal")));
poolConfig.setTestOnBorrow(Boolean.parseBoolean(pro.getProperty("thrift_testOnBorrow")));
poolConfig.setTestOnReturn(Boolean.parseBoolean(pro.getProperty("thrift_testOnReturn")));
poolConfig.setTestOnCreate(Boolean.parseBoolean(pro.getProperty("thrift_testOnCreate")));
poolConfig.setTestWhileIdle(Boolean.parseBoolean(pro.getProperty("thrift_testWhileIdle")));
poolConfig.setLifo(Boolean.parseBoolean(pro.getProperty("thrift_lifo")));
// 初始化对象池
socketPool = new GenericObjectPool<TSocket>(
new TSocketFactory(pro.getProperty("thrift_ip"), Integer.parseInt(pro.getProperty("thrift_port"))), poolConfig);
}
public TSocket borrowObject() throws Exception {
return socketPool.borrowObject();
}
public void returnObject(TSocket socket) {
socketPool.returnObject(socket);
}
}
相关配置:
thrift_ip=127.0.0.1
thrift_port=8001
thrift_maxTotal=1024 //最大数
thrift_minIdle=100 //最小空闲
thrift_maxIdle=100 //最大空闲
thrift_maxWait=3000 //最大等待时间
thrift_blockWhenExhausted=true//池对象耗尽之后是否阻塞,maxWait<0时一直等待
thrift_testOnBorrow=true//取对象是验证
thrift_testOnReturn=true //回收验证
thrift_testOnCreate=true//创建时验证
thrift_testWhileIdle=false//空闲验证
thrift_lifo=false//后进先出
3. 使用上面封装的连接池
private static TSocketPool rpcSocketPool;
static {
rpcSocketPool = new TSocketPool(Thread.currentThread().getContextClassLoader().getResourceAsStream("rpc.properties"));
}
public static void callSyn(String data) {
try {
TSocket socket = null;
try {
// 从池中获取对象
socket = rpcSocketPool.borrowObject();
} catch (Exception e1) {
logger.error("Could not get a TSocket from the pool", e1);
}
if (null == socket) {
return;
}
try {
//下面是thrift部分
TTransport transport = new TFramedTransport(socket);
TProtocol protocol = new TBinaryProtocol(transport);// 使用二进制协议
TMultiplexedProtocol impl = new TMultiplexedProtocol(protocol, "service");
ITKmonitorMQService.Client client = new ITKmonitorMQService.Client(impl);
//具体调用业务
client.add(data);
} catch (Exception e) {
logger.error("", e);
} finally {
rpcSocketPool.returnObject(socket);// 对象返回到池中
}
} catch (Throwable e) {
logger.error("", e);
}
}