Java GenericObjectPool 物件池化技術--SpringBoot sftp 連線池工具類
一個物件池包含一組已經初始化過且可以使用的物件,而可以在有需求時建立和銷燬物件。池的使用者可以從池子中取得物件,對其進行操作處理,並在不需要時歸還給池子而非直接銷燬它。這是一種特殊的工廠物件。
BasePooledObjectFactory 物件池化技術 的使用
Pom.xml
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-pool2</artifactId>
<version>2.7.0</version>
</dependency>
MqttConnection.java
package com.vipsoft.mqtt.pool;
public class MqttConnection {
private String mqttClient;
;
public MqttConnection(String mqttClient) {
this.mqttClient = mqttClient;
}
public String getMqttClient() {
return mqttClient;
}
public void setMqttClient(String mqttClient) {
this.mqttClient = mqttClient;
}
/**
* 推送方法訊息
*/
public void publish(String msg) throws Exception {
System.out.println("物件" + mqttClient + ":" + "執行任務" + msg);
}
@Override
public String toString() {
return "MqttConnection{" + "id=" + mqttClient + '}';
}
}
MqttConnectionFactory.java
package com.vipsoft.mqtt.pool;
import org.apache.commons.pool2.BasePooledObjectFactory;
import org.apache.commons.pool2.PooledObject;
import org.apache.commons.pool2.impl.DefaultPooledObject;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.concurrent.atomic.AtomicInteger;
public class MqttConnectionFactory extends BasePooledObjectFactory<MqttConnection> {
private static final Logger logger = LoggerFactory.getLogger(MqttConnectionFactory.class);
// AtomicInteger是一個提供原子操作的Integer類,透過執行緒安全的方式操作加減
private AtomicInteger counter = new AtomicInteger();
/**
* 在物件池中建立物件
*
* @return
* @throws Exception
*/
@Override
public MqttConnection create() throws Exception {
// 實現執行緒安全避免在高併發的場景下出現clientId重複導致無法建立連線的情況
int count = this.counter.addAndGet(1);
MqttConnection mqttConnection = new MqttConnection("MqttConnection:" + count);
logger.info("在物件池中建立物件 {}", mqttConnection.toString());
return mqttConnection;
}
/**
* common-pool2 中建立了 DefaultPooledObject 物件對物件池中物件進行的包裝。
* 將我們自定義的物件放置到這個包裝中,工具會統計物件的狀態、建立時間、更新時間、返回時間、出借時間、使用時間等等資訊進行統計
*
* @param mqttConnection
* @return
*/
@Override
public PooledObject<MqttConnection> wrap(MqttConnection mqttConnection) {
logger.info("封裝預設返回型別 {}", mqttConnection.toString());
return new DefaultPooledObject<>(mqttConnection);
}
/**
* 銷燬物件
*
* @param p 物件池
* @throws Exception 異常
*/
@Override
public void destroyObject(PooledObject<MqttConnection> p) throws Exception {
logger.info("銷燬物件 {}", p.getObject().getMqttClient());
super.destroyObject(p);
}
/**
* 校驗物件是否可用
*
* @param p 物件池
* @return 物件是否可用結果,boolean
*/
@Override
public boolean validateObject(PooledObject<MqttConnection> p) {
logger.info("校驗物件是否可用 {}", p.getObject().getMqttClient());
return super.validateObject(p);
}
/**
* 啟用鈍化的物件系列操作
*
* @param p 物件池
* @throws Exception 異常資訊
*/
@Override
public void activateObject(PooledObject<MqttConnection> p) throws Exception {
logger.info("啟用鈍化的物件 {}", p.getObject().getMqttClient());
super.activateObject(p);
}
/**
* 鈍化未使用的物件
*
* @param p 物件池
* @throws Exception 異常資訊
*/
@Override
public void passivateObject(PooledObject<MqttConnection> p) throws Exception {
logger.info("鈍化未使用的物件 {}", p.getObject().getMqttClient());
super.passivateObject(p);
}
}
PoolTest.java
package com.vipsoft.mqtt;
import cn.hutool.core.date.DateUtil;
import com.vipsoft.mqtt.pool.MqttConnection;
import com.vipsoft.mqtt.pool.MqttConnectionFactory;
import org.apache.commons.pool2.impl.GenericObjectPool;
import org.apache.commons.pool2.impl.GenericObjectPoolConfig;
import org.junit.jupiter.api.Test;
import org.springframework.boot.test.context.SpringBootTest;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.atomic.AtomicInteger;
@SpringBootTest
public class PoolTest {
@Test
void basePooledTest() throws InterruptedException {
AtomicInteger atomicInteger = new AtomicInteger();
int excutorCount = 15;
CountDownLatch countDownLatch = new CountDownLatch(excutorCount);
// =====================建立執行緒池=====================
ExecutorService excutor = Executors.newFixedThreadPool(5);
// =====================建立物件池=====================
// 物件池工廠
MqttConnectionFactory personPoolFactory = new MqttConnectionFactory();
// 物件池配置
GenericObjectPoolConfig<MqttConnection> objectPoolConfig = new GenericObjectPoolConfig<>();
objectPoolConfig.setMaxTotal(50);
// 物件池
GenericObjectPool<MqttConnection> mqttPool = new GenericObjectPool<>(personPoolFactory, objectPoolConfig);
// =====================測試物件池=====================
// 迴圈100次,從執行緒池中取多個多執行緒執行任務,來測試物件池
for (int i = 0; i < excutorCount; i++) {
excutor.submit(new Thread(() -> {
// 模擬從物件池取出物件,執行任務
MqttConnection mqtt = null;
try {
// 從物件池取出物件
mqtt = mqttPool.borrowObject();
// 讓物件工作
int count = atomicInteger.addAndGet(1);
mqtt.publish("Id:" + count + " Time: " + DateUtil.now());
} catch (Exception e) {
e.printStackTrace();
} finally {
// 回收物件到物件池
if (mqtt != null) {
mqttPool.returnObject(mqtt);
}
countDownLatch.countDown();
}
}));
}
countDownLatch.await();
}
}