maven项目引入依赖:
<!-- https://mvnrepository.com/artifact/org.apache.commons/commons-pool2 --> <dependency> <groupId>org.apache.commons</groupId> <artifactId>commons-pool2</artifactId> <version>2.4.2</version> </dependency> |
基本介绍:
在此例中,对象池中存储的是elasticsearch TransportClient,是个大对象(生成比较耗时)。我们使用common pool池化技术,预加载client对象,使用的时候只需要从池中拿即可。
基本api调用方式如下:
GenericObjectPoolConfig poolConfig = new GenericObjectPoolConfig();//对象池配置类,不写也可以,采用默认配置 poolConfig.setMaxTotal(list.length);//采用默认配置maxTotal是8,池中有8个client EsClientPoolFactory esClientPoolFactory = new EsClientPoolFactory();//要池化的对象的工厂类,这个是我们要实现的类 GenericObjectPool<TransportClient> clientPool = new GenericObjectPool<>(esClientPoolFactory,poolConfig);//利用对象工厂类和配置类生成对象池 client = clientPool.borrowObject(); //从池中取一个对象 clientPool.returnObject(client);//使用完毕之后,归还对象
下面是工厂类代码:
import org.apache.commons.pool2.PooledObject; import org.apache.commons.pool2.PooledObjectFactory; import org.apache.commons.pool2.impl.DefaultPooledObject; import org.elasticsearch.client.transport.TransportClient; import org.elasticsearch.common.settings.Settings; import org.elasticsearch.common.transport.InetSocketTransportAddress; import org.elasticsearch.transport.client.PreBuiltTransportClient; import java.net.InetAddress; import java.net.UnknownHostException; public class EsClientPoolFactory implements PooledObjectFactory<TransportClient> { @Override //生成pooledObject public PooledObject<TransportClient> makeObject() throws Exception { Settings settings = Settings.builder().put("cluster.name","elasticsearch").build(); TransportClient client = null; try { client = new PreBuiltTransportClient(settings) .addTransportAddress(new InetSocketTransportAddress(InetAddress.getByName("localhost"),9300)); } catch (UnknownHostException e) { e.printStackTrace(); } return new DefaultPooledObject<TransportClient>(client); } @Override //销毁对象 public void destroyObject(PooledObject<TransportClient> pooledObject) throws Exception { TransportClient client = pooledObject.getObject(); client.close(); } @Override //验证对象 public boolean validateObject(PooledObject<TransportClient> pooledObject) { return true; } @Override //激活对象 public void activateObject(PooledObject<TransportClient> pooledObject) throws Exception { System.out.println("activate esClient"); } @Override //钝化对象 public void passivateObject(PooledObject<TransportClient> pooledObject) throws Exception { System.out.println("passivate Object"); } }
①:当在GenericObjectPool类中调用borrowObject方法时,如果当前对象池中没有空闲的对象,GenericObjectPool会调用这个方法,创建一个对象,并把这个对象封装到PooledObject类中,并交给对象池管理。
②:void destroyObject(PooledObject<T> p) throws Exception;
销毁对象,当对象池检测到某个对象的空闲时间(idle)超时,或使用完对象归还到对象池之前被检测到对象已经无效时,就会调用这个方法销毁对象。对象的销毁一般和业务相关,但必须明确的是,当调用这个方法之后,对象的生命周期必须结果。如果是对象是线程,线程必须已结束,如果是socket,socket必须已close,如果是文件操作,文件数据必须已flush,且文件正常关闭。
③:boolean validateObject(PooledObject<T> p);
检测一个对象是否有效。在对象池中的对象必须是有效的,这个有效的概念是,从对象池中拿出的对象是可用的。比如,如果是socket,那么必须保证socket是连接可用的。在从对象池获取对象或归还对象到对象池时,会调用这个方法,判断对象是否有效,如果无效就会销毁。
④:void activateObject(PooledObject<T> p) throws Exception;
激活一个对象或者说启动对象的某些操作。比如,如果对象是socket,如果socket没有连接,或意外断开了,可以在这里启动socket的连接。它会在检测空闲对象的时候,如果设置了测试空闲对象是否可以用,就会调用这个方法,在borrowObject的时候也会调用。另外,如果对象是一个包含参数的对象,可以在这里进行初始化。让使用者感觉这是一个新创建的对象一样。
⑤:void passivateObject(PooledObject<T> p) throws Exception;
钝化一个对象。在向对象池归还一个对象是会调用这个方法。这里可以对对象做一些清理操作。比如清理掉过期的数据,下次获得对象时,不受旧数据的影响。
一般来说activateObject和passivateObject是成对出现的。前者是在对象从对象池取出时做一些操作,后者是在对象归还到对象池做一些操作,可以根据自己的业务需要进行取舍。