当前位置: 首页 > news >正文

apache.commons.pool2 使用指南

apache.commons.pool2 使用指南

为什么要使用池

创建对象耗时较长,多线程频繁调用等因素限制了我们不能每次使用时都重新创建对象,使用池化思想将对象放进池内,不同线程使用同一个池来获取对象,极大的减少每次业务的调用时间。

一个线程内多次使用这个对象所建立的连接。

使用场景

  • 数据库连接池:HikariCP、Druid
  • 自定义业务连接池:耗时的客户端连接远程服务端

如何使用

1、创建对象客户端

package com.ncst.client.mcc;import lombok.extern.slf4j.Slf4j;
import java.util.Objects;/*** @Author: Lisy* @Description: MCC 操作工具类*/
@Slf4j
public class MccClient {public MccClient() {}public void putMc(String key, String value) {if (Objects.isNull(key)) {throw new IllegalArgumentException("The key argument cannot be null");}log.info("{}=={}", key, value);}public String getMc(String key) {if (Objects.isNull(key)) {throw new IllegalArgumentException("The " + key + " argument cannot be null");}return "";}}

2、创建池工厂类

package com.ncst.client.mcc;import org.apache.commons.pool2.PooledObject;
import org.apache.commons.pool2.PooledObjectFactory;
import org.apache.commons.pool2.impl.DefaultPooledObject;/*** @Author: Lisy* @Description: 对象池工厂*/
public class MccClientFactory implements PooledObjectFactory<MccClient> {public MccClientFactory() {}@Overridepublic PooledObject<MccClient> makeObject() {MccClient dccClient = new MccClient();return new DefaultPooledObject<>(dccClient);}@Overridepublic void destroyObject(PooledObject<MccClient> p) {MccClient object = p.getObject();object.close();}@Overridepublic boolean validateObject(PooledObject<MccClient> p) {// 验证对象是否可用的逻辑,如果需要return true;}@Overridepublic void activateObject(PooledObject<MccClient> p) {// 激活对象的逻辑,如果需要}@Overridepublic void passivateObject(PooledObject<MccClient> p) {// 钝化对象的逻辑,如果需要}}

3、对象池管理类

用于管理保存的池对象,单例模式

shutdown 方法在不使用时关闭掉对应任务的所有池连接

package com.ncst.client;import com.ncst.client.mcc.MccClient;
import com.ncst.client.mcc.MccClientFactory;
import org.apache.commons.pool2.impl.GenericObjectPool;
import org.apache.commons.pool2.impl.GenericObjectPoolConfig;import java.util.Objects;
import java.util.concurrent.ConcurrentHashMap;/*** @Author: Lisy* @Description: 对象池管理*/
public class MccClientPoolManager {private static volatile MccClientPoolManager INSTANCE;private MccClientPoolManager() {}public static MccClientPoolManager getInstance() {if (Objects.isNull(INSTANCE)) {synchronized (MccClientPoolManager.class) {if (Objects.isNull(INSTANCE)) {INSTANCE = new MccClientPoolManager();}}}return INSTANCE;}/*** key-jobUuid, value-每一个任务池*/private final ConcurrentHashMap<String, GenericObjectPool<MccClient>> POOL_MAP = new ConcurrentHashMap<>();public GenericObjectPool<MccClient> getPool(String jobId, GenericObjectPoolConfig<MccClient> poolConfig) {return POOL_MAP.computeIfAbsent(jobId, k -> new GenericObjectPool<>(new MccClientFactory(), poolConfig));}public void shutdown(String jobId) {GenericObjectPool<MccClient> dccClientGenericObjectPool = POOL_MAP.get(jobId);if (Objects.nonNull(dccClientGenericObjectPool)) {dccClientGenericObjectPool.close();}}
}

4、使用

通过多线程来模拟实际使用场景,如果使用默认poolConfig,那么最大池大小为8个,最多创建8个对象。

通过CountDownLatch 来等待所有任务完成

通过 MccClientPoolManager.getInstance().shutdown(“key”); 来关闭池

“key” 可根据业务逻辑自行定义

 public static void main(String[] args) throws InterruptedException {int num = 20;CountDownLatch latch = new CountDownLatch(num);for (int i = 0; i < num; i++) {int finalI = i;CompletableFuture.runAsync(() -> {try {GenericObjectPool<MccClient> pool2 = MccClientPoolManager.getInstance().getPool("key", new GenericObjectPoolConfig<>());MccClient mccClient = null;try {mccClient = pool2.borrowObject();mccClient.putMc("" + finalI, "value" + finalI);} finally {if (Objects.nonNull(mccClient)) {pool2.returnObject(mccClient);}}} catch (Exception e) {logger.error(e.getMessage(), e);} finally {latch.countDown();}});}latch.await();MccClientPoolManager.getInstance().shutdown("key");}

源码解析-create()

510:private PooledObject<T> create() throws Exception
创建对象时锁住makeObjectCountLock,判断当前已创建对象是否大于设置的池大小,如果未超过则create==true超过则判断已有的池大小是否为0,如果为0返回create==false,
不为0等待正在创建的对象,执行makeObjectCountLock.waitcreate 为true则创建对象,执行 public PooledObject<T> makeObject()创建完对象后判断是否为空,如果为空将已创建对象 cretaeCount--,并抛出异常验证对象是否可用,如果不可用返回null,并cretaeCount--在finally 中锁住 makeObjectCount lock,将makeObjectCount--,唤醒锁中所有等待的对象将对象放入allObjects map中
http://www.lryc.cn/news/409828.html

相关文章:

  • 【Python面试题收录】Python编程基础练习题②(数据类型+文件操作+时间操作)
  • typescript 定义类型
  • 基于Java+SpringBoot+Vue的的课程作业管理系统
  • 分布式日志分析系统--ELK
  • Linux初学基本命令
  • 如何优化PyTorch以加快模型训练速度?
  • 用最简单的方法对大数据进行处理 vs spark(不需要安装大数据处理工具)
  • 非线性校正算法在红外测温中的应用
  • python----线程、进程、协程的区别及多线程详解
  • 将 magma example 改写成 cusolver example eqrf
  • 微信小程序教程007:数据绑定
  • Git -- git stash 暂存
  • 基于YOLO的植物病害识别系统:从训练到部署全攻略
  • 数据库开发:MySQL基础(二)
  • 实现物理数据库迁移到云上
  • [Spring] MyBatis操作数据库(进阶)
  • 【Websim.ai】一句话让AI帮你生成一个网页
  • 云计算实训16——关于web,http协议,https协议,apache,nginx的学习与认知
  • 2024年必备技能:小红书笔记评论自动采集,零基础也能学会的方法
  • 【Gitlab】SSH配置和克隆仓库
  • [Day 35] 區塊鏈與人工智能的聯動應用:理論、技術與實踐
  • Vue 3 中使用 inMap.js 实现蜂窝热力图的可视化
  • nginx隐藏server及版本号
  • Oracle DBMS_XPLAN包
  • 【ffmpeg命令入门】分离音视频流
  • 小红书笔记评论采集全攻略:三种高效方法教你批量导出
  • 实战:ZooKeeper 操作命令和集群部署
  • linux运维一天一个shell命令之 top详解
  • 大模型微调:参数高效微调(PEFT)方法总结
  • Spark+实例解读