池化技术
说明
一个对象池包含一组已经初始化过且可以使用的对象,而可以在有需求时创建和销毁对象。池的用户可以从池子中取得对象,对其进行操作处理,并在不需要时归还给池子而非直接销毁它。这是一种特殊的工厂对象。
场景
1,资源受限的, 不需要可伸缩性的环境(cpu\内存等物理资源有限): cpu性能不够强劲, 内存比较紧张, 垃圾收集, 内存抖动会造成比较大的影响, 需要提高内存管理效率, 响应性比吞吐量更为重要;
2,数量受限的, 比如数据库连接;
3,创建成本高的对象, 可以考虑是否池化, 比较常见的有线程池(ThreadPoolExecutor), 字节数组池等。
1,依赖包
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-pool2</artifactId>
<version>2.7.0</version>
</dependency>
2,对象类
package club.mydlq.pool;
/**
* 对象
*/
public class Person {
private Integer id;;
public Person(Integer id) {
this.id = id;
}
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public void executeTask(){
System.out.println("对象" + id + ":" + "执行任务");
}
@Override
public String toString() {
return "Person{" + "id=" + id + '}';
}
}
3,对象池工厂
package club.mydlq.pool;
import org.apache.commons.pool2.BasePooledObjectFactory;
import org.apache.commons.pool2.PooledObject;
import org.apache.commons.pool2.impl.DefaultPooledObject;
import java.util.concurrent.atomic.AtomicInteger;
/**
* 对象池工厂
*/
public class PersonPoolFactory extends BasePooledObjectFactory<Person> {
// AtomicInteger是一个提供原子操作的Integer类,通过线程安全的方式操作加减
private AtomicInteger atomicInteger = new AtomicInteger(1);
/**
* 在对象池中创建对象
*
* @return 自定义对象
*/
public Person create() {
return new Person(atomicInteger.getAndAdd(1));
}
/**
* common-pool2 中创建了 DefaultPooledObject 对象对对象池中对象进行的包装。
* 将我们自定义的对象放置到这个包装中,工具会统计对象的状态、创建时间、更新时间、返回时间、出借时间、使用时间等等信息进行统计
*
* @param person 自定义对象
* @return 对象池
*/
public PooledObject<Person> wrap(Person person) {
return new DefaultPooledObject<>(person);
}
/**
* 销毁对象
* @param p 对象池
* @throws Exception 异常
*/
@Override
public void destroyObject(PooledObject<Person> p) throws Exception {
super.destroyObject(p);
}
/**
* 校验对象是否可用
* @param p 对象池
* @return 对象是否可用结果,boolean
*/
@Override
public boolean validateObject(PooledObject<Person> p) {
return super.validateObject(p);
}
/**
* 激活钝化的对象系列操作
* @param p 对象池
* @throws Exception 异常信息
*/
@Override
public void activateObject(PooledObject<Person> p) throws Exception {
super.activateObject(p);
}
/**
* 钝化未使用的对象
* @param p 对象池
* @throws Exception 异常信息
*/
@Override
public void passivateObject(PooledObject<Person> p) throws Exception {
super.passivateObject(p);
}
}
4,测试对象池的 main 方法
package club.mydlq;
import club.mydlq.pool.Person;
import club.mydlq.pool.PersonPoolFactory;
import org.apache.commons.pool2.impl.GenericObjectPool;
import org.apache.commons.pool2.impl.GenericObjectPoolConfig;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
/**
* 测试对象池的 main 方法
*/
public class Application {
public static void main(String[] args) {
// =====================创建线程池=====================
ExecutorService excutor = Executors.newFixedThreadPool(10);
// =====================创建对象池=====================
// 对象池工厂
PersonPoolFactory personPoolFactory = new PersonPoolFactory();
// 对象池配置
GenericObjectPoolConfig<Person> objectPoolConfig = new GenericObjectPoolConfig<>();
objectPoolConfig.setMaxTotal(5);
// 对象池
GenericObjectPool<Person> personPool = new GenericObjectPool<>(personPoolFactory, objectPoolConfig);
// =====================测试对象池=====================
// 循环100次,从线程池中取多个多线程执行任务,来测试对象池
for (int i = 0; i < 15; i++) {
excutor.submit(new Thread(() -> {
// 模拟从对象池取出对象,执行任务
Person person = null;
try {
// 从对象池取出对象
person = personPool.borrowObject();
// 让对象工作
person.executeTask();
} catch (Exception e) {
e.printStackTrace();
} finally {
// 回收对象到对象池
if (person != null) {
personPool.returnObject(person);
}
}
}));
}
}
}