mirror of
https://gitee.com/chinabugotech/hutool.git
synced 2025-04-19 03:01:48 +08:00
add pool
This commit is contained in:
parent
1eacd29d99
commit
a7abbf5402
@ -22,23 +22,62 @@ import java.io.Serializable;
|
||||
* <li>{@link #returnObject(Poolable)}对象归还。</li>
|
||||
* </ul>
|
||||
*
|
||||
* 对于对象池中对象维护,通过{@link PoolConfig#getMaxIdle()}控制,规则如下:
|
||||
* <ul>
|
||||
* <li>如果借出量很多,则不断扩容,直到达到{@link PoolConfig#getMaxSize()}</li>
|
||||
* <li>如果池对象闲置超出{@link PoolConfig#getMaxIdle()},则销毁。</li>
|
||||
* <li>实际使用中,池中对象可能少于{@link PoolConfig#getMinSize()}</li>
|
||||
* </ul>
|
||||
*
|
||||
* @param <T> 对象类型
|
||||
* @author looly
|
||||
* @author Looly
|
||||
*/
|
||||
public interface ObjectPool<T> extends Closeable, Serializable {
|
||||
|
||||
/**
|
||||
* 借出对象
|
||||
* 借出对象,流程如下:
|
||||
* <ol>
|
||||
* <li>从池中取出对象</li>
|
||||
* <li>检查对象可用性</li>
|
||||
* <li>如果无可用对象,扩容池并创建新对象</li>
|
||||
* <li>继续取对象</li>
|
||||
* </ol>
|
||||
*
|
||||
* @return 对象
|
||||
*/
|
||||
Poolable<T> borrowObject();
|
||||
|
||||
/**
|
||||
* 归还对象
|
||||
* 归还对象,流程如下:
|
||||
* <ol>
|
||||
* <li>检查对象可用性</li>
|
||||
* <li>不可用则销毁之</li>
|
||||
* <li>可用则入池</li>
|
||||
* </ol>
|
||||
*
|
||||
* @param obj 对象
|
||||
* @return this
|
||||
*/
|
||||
ObjectPool<T> returnObject(final Poolable<T> obj);
|
||||
|
||||
/**
|
||||
* 获取持有对象总数(包括空闲对象 + 正在使用对象数)
|
||||
*
|
||||
* @return 总数
|
||||
*/
|
||||
int getTotal();
|
||||
|
||||
/**
|
||||
* 获取空闲对象数,即在池中的对象数
|
||||
*
|
||||
* @return 空闲对象数,-1表示此信息不可用
|
||||
*/
|
||||
int getIdleCount();
|
||||
|
||||
/**
|
||||
* 获取已经借出的对象(正在使用的)对象数
|
||||
*
|
||||
* @return 正在使用的对象数,-1表示此对象不可用
|
||||
*/
|
||||
int getActiveCount();
|
||||
}
|
||||
|
@ -12,54 +12,124 @@
|
||||
|
||||
package org.dromara.hutool.core.pool;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
/**
|
||||
* 对象池配置,提供基本的配置项,包括:
|
||||
* <ul>
|
||||
* <li>最小池大小(初始大小)</li>
|
||||
* <li>最大池大小</li>
|
||||
* <li>最大池大小</li>
|
||||
* <li>最长等待时间</li>
|
||||
* <li>最长空闲时间</li>
|
||||
* </ul>
|
||||
*
|
||||
* @author Daniel, Looly
|
||||
*/
|
||||
public class PoolConfig {
|
||||
private int minSize;
|
||||
private int maxSize;
|
||||
public class PoolConfig implements Serializable {
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
private long maxWait;
|
||||
/**
|
||||
* 创建{@code PoolConfig}
|
||||
*
|
||||
* @return {@code PoolConfig}
|
||||
*/
|
||||
public static PoolConfig of() {
|
||||
return new PoolConfig();
|
||||
}
|
||||
|
||||
/**
|
||||
* 最小(初始)池大小
|
||||
*/
|
||||
private int minSize = 5;
|
||||
/**
|
||||
* 最大池大小
|
||||
*/
|
||||
private int maxSize = 20;
|
||||
|
||||
/**
|
||||
* 最长等待时间,用于在借出对象时,等待最长时间(默认5秒)。
|
||||
*/
|
||||
private long maxWait = 5000;
|
||||
/**
|
||||
* 最长空闲时间(在池中时间)
|
||||
*/
|
||||
private long maxIdle;
|
||||
|
||||
/**
|
||||
* 获取最小(初始)池大小
|
||||
*
|
||||
* @return 最小(初始)池大小
|
||||
*/
|
||||
public int getMinSize() {
|
||||
return minSize;
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置最小(初始)池大小
|
||||
*
|
||||
* @param minSize 最小(初始)池大小
|
||||
* @return this
|
||||
*/
|
||||
public PoolConfig setMinSize(final int minSize) {
|
||||
this.minSize = minSize;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取最大池大小
|
||||
*
|
||||
* @return 最大池大小
|
||||
*/
|
||||
public int getMaxSize() {
|
||||
return maxSize;
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置最大池大小
|
||||
*
|
||||
* @param maxSize 最大池大小
|
||||
* @return this
|
||||
*/
|
||||
public PoolConfig setMaxSize(final int maxSize) {
|
||||
this.maxSize = maxSize;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取最长等待时间,用于在借出对象时,等待最长时间。
|
||||
*
|
||||
* @return 最长等待时间,用于在借出对象时,等待最长时间。
|
||||
*/
|
||||
public long getMaxWait() {
|
||||
return maxWait;
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置最长等待时间,用于在借出对象时,等待最长时间。
|
||||
*
|
||||
* @param maxWait 最长等待时间,用于在借出对象时,等待最长时间。
|
||||
* @return this
|
||||
*/
|
||||
public PoolConfig setMaxWait(final long maxWait) {
|
||||
this.maxWait = maxWait;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取最长空闲时间(在池中时间)
|
||||
*
|
||||
* @return 最长空闲时间(在池中时间),小于等于0表示不限制
|
||||
*/
|
||||
public long getMaxIdle() {
|
||||
return maxIdle;
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置最长空闲时间(在池中时间)
|
||||
*
|
||||
* @param maxIdle 最长空闲时间(在池中时间),小于等于0表示不限制
|
||||
* @return this
|
||||
*/
|
||||
public PoolConfig setMaxIdle(final long maxIdle) {
|
||||
this.maxIdle = maxIdle;
|
||||
return this;
|
||||
|
@ -14,6 +14,18 @@ package org.dromara.hutool.core.pool;
|
||||
|
||||
import org.dromara.hutool.core.lang.wrapper.Wrapper;
|
||||
|
||||
/**
|
||||
* 池化对象
|
||||
*
|
||||
* @param <T> 对象类型
|
||||
* @author Looly
|
||||
*/
|
||||
public interface Poolable<T> extends Wrapper<T> {
|
||||
void returnObject();
|
||||
|
||||
/**
|
||||
* 获取最后借出时间
|
||||
*
|
||||
* @return 最后借出时间
|
||||
*/
|
||||
long getLastBorrow();
|
||||
}
|
||||
|
@ -13,7 +13,9 @@
|
||||
package org.dromara.hutool.core.pool.partition;
|
||||
|
||||
import org.dromara.hutool.core.io.IoUtil;
|
||||
import org.dromara.hutool.core.pool.*;
|
||||
import org.dromara.hutool.core.pool.ObjectFactory;
|
||||
import org.dromara.hutool.core.pool.ObjectPool;
|
||||
import org.dromara.hutool.core.pool.Poolable;
|
||||
import org.dromara.hutool.core.thread.ThreadUtil;
|
||||
|
||||
import java.io.IOException;
|
||||
@ -58,6 +60,7 @@ public class PartitionObjectPool<T> implements ObjectPool<T> {
|
||||
*
|
||||
* @return 总数
|
||||
*/
|
||||
@Override
|
||||
public int getTotal() {
|
||||
int size = 0;
|
||||
for (final PoolPartition<T> subPool : partitions) {
|
||||
@ -67,16 +70,33 @@ public class PartitionObjectPool<T> implements ObjectPool<T> {
|
||||
}
|
||||
|
||||
@Override
|
||||
public Poolable<T> borrowObject() {
|
||||
checkClosed();
|
||||
final int partitionIndex = (int) (ThreadUtil.currentThreadId() % config.getPartitionSize());
|
||||
return this.partitions[partitionIndex].borrowObject();
|
||||
public int getIdleCount() {
|
||||
int size = 0;
|
||||
for (final PoolPartition<T> subPool : partitions) {
|
||||
size += subPool.getIdleCount();
|
||||
}
|
||||
return size;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getActiveCount() {
|
||||
int size = 0;
|
||||
for (final PoolPartition<T> subPool : partitions) {
|
||||
size += subPool.getActiveCount();
|
||||
}
|
||||
return size;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Poolable<T> borrowObject() {
|
||||
checkClosed();
|
||||
return this.partitions[getPartitionIndex(this.config)].borrowObject();
|
||||
}
|
||||
|
||||
@Override
|
||||
public PartitionObjectPool<T> returnObject(final Poolable<T> obj) {
|
||||
checkClosed();
|
||||
final int partitionIndex = (int) (ThreadUtil.currentThreadId() % config.getPartitionSize());
|
||||
this.partitions[partitionIndex].returnObject(obj);
|
||||
this.partitions[getPartitionIndex(this.config)].returnObject(obj);
|
||||
return this;
|
||||
}
|
||||
|
||||
@ -86,10 +106,32 @@ public class PartitionObjectPool<T> implements ObjectPool<T> {
|
||||
IoUtil.closeQuietly(this.partitions);
|
||||
}
|
||||
|
||||
protected BlockingQueue<Poolable<T>> createBlockingQueue(final PoolConfig poolConfig) {
|
||||
/**
|
||||
* 创建阻塞队列,默认为{@link ArrayBlockingQueue}<br>
|
||||
* 如果需要自定义队列类型,子类重写此方法
|
||||
*
|
||||
* @param poolConfig 池配置
|
||||
* @return 队列
|
||||
*/
|
||||
protected BlockingQueue<PartitionPoolable<T>> createBlockingQueue(final PartitionPoolConfig poolConfig) {
|
||||
return new ArrayBlockingQueue<>(poolConfig.getMaxSize());
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取当前线程被分配的分区<br>
|
||||
* 默认根据线程ID(TID)取分区大小余数<br>
|
||||
* 如果需要自定义,子类重写此方法
|
||||
*
|
||||
* @param poolConfig 池配置
|
||||
* @return 分配的分区
|
||||
*/
|
||||
protected int getPartitionIndex(final PartitionPoolConfig poolConfig) {
|
||||
return (int) (ThreadUtil.currentThreadId() % poolConfig.getPartitionSize());
|
||||
}
|
||||
|
||||
/**
|
||||
* 检查池是否关闭
|
||||
*/
|
||||
private void checkClosed() {
|
||||
if (this.closed) {
|
||||
throw new IllegalStateException("Object Pool is closed!");
|
||||
|
@ -20,12 +20,34 @@ import org.dromara.hutool.core.pool.PoolConfig;
|
||||
* @author looly
|
||||
*/
|
||||
public class PartitionPoolConfig extends PoolConfig {
|
||||
private int partitionSize;
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
/**
|
||||
* 创建{@code PartitionPoolConfig}
|
||||
*
|
||||
* @return {@code PartitionPoolConfig}
|
||||
*/
|
||||
public static PartitionPoolConfig of() {
|
||||
return new PartitionPoolConfig();
|
||||
}
|
||||
|
||||
private int partitionSize = 4;
|
||||
|
||||
/**
|
||||
* 获取分区大小
|
||||
*
|
||||
* @return 分区大小
|
||||
*/
|
||||
public int getPartitionSize() {
|
||||
return partitionSize;
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置分区大小
|
||||
*
|
||||
* @param partitionSize 分区大小
|
||||
* @return this
|
||||
*/
|
||||
public PartitionPoolConfig setPartitionSize(final int partitionSize) {
|
||||
this.partitionSize = partitionSize;
|
||||
return this;
|
||||
|
@ -14,14 +14,27 @@ package org.dromara.hutool.core.pool.partition;
|
||||
|
||||
import org.dromara.hutool.core.pool.Poolable;
|
||||
|
||||
/**
|
||||
* 分区可池化对象,此对象会同时持有原始对象和所在的分区
|
||||
*
|
||||
* @param <T> 对象类型
|
||||
*/
|
||||
public class PartitionPoolable<T> implements Poolable<T> {
|
||||
|
||||
private final T raw;
|
||||
private final PoolPartition<T> partition;
|
||||
private long lastBorrow;
|
||||
|
||||
public PartitionPoolable(final T raw, PoolPartition<T> partition) {
|
||||
/**
|
||||
* 构造
|
||||
*
|
||||
* @param raw 原始对象
|
||||
* @param partition 对象所在分区
|
||||
*/
|
||||
public PartitionPoolable(final T raw, final PoolPartition<T> partition) {
|
||||
this.raw = raw;
|
||||
this.partition = partition;
|
||||
this.lastBorrow = System.currentTimeMillis();
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -29,8 +42,24 @@ public class PartitionPoolable<T> implements Poolable<T> {
|
||||
return this.raw;
|
||||
}
|
||||
|
||||
@Override
|
||||
/**
|
||||
* 归还对象
|
||||
*/
|
||||
public void returnObject() {
|
||||
this.partition.returnObject(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getLastBorrow() {
|
||||
return lastBorrow;
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置最后借出时间,在成功借出此对象时更新时间
|
||||
*
|
||||
* @param lastBorrow 最后借出时间
|
||||
*/
|
||||
protected void setLastBorrow(final long lastBorrow) {
|
||||
this.lastBorrow = lastBorrow;
|
||||
}
|
||||
}
|
||||
|
@ -14,24 +14,52 @@ package org.dromara.hutool.core.pool.partition;
|
||||
|
||||
import org.dromara.hutool.core.exception.HutoolException;
|
||||
import org.dromara.hutool.core.pool.ObjectFactory;
|
||||
import org.dromara.hutool.core.pool.ObjectPool;
|
||||
import org.dromara.hutool.core.pool.PoolConfig;
|
||||
import org.dromara.hutool.core.pool.Poolable;
|
||||
|
||||
import java.io.Closeable;
|
||||
import java.io.IOException;
|
||||
import java.util.concurrent.BlockingQueue;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
public class PoolPartition<T> implements Closeable {
|
||||
/**
|
||||
* 对象池分区<br>
|
||||
* 一个分区实际为一个小的对象池,持有一个阻塞队列。<br>
|
||||
* 初始化时创建{@link PoolConfig#getMinSize()}个对象作为初始池对象.
|
||||
*
|
||||
* <p>
|
||||
* 当借出对象时,从队列头部取出并验证,验证通过后使用,验证不通过直接调用{@link #free(Poolable)} 销毁并重新获取,
|
||||
* 当池中对象都被借出(空了),创建新的对象并入队列,直到队列满为止,当满时等待归还,超时则报错。
|
||||
* </p>
|
||||
*
|
||||
* <p>
|
||||
* 当归还对象时,验证对象,不可用销毁之,可用入队列。
|
||||
* </p>
|
||||
*
|
||||
* <p>
|
||||
* 一个分区队列的实际
|
||||
* </p>
|
||||
*
|
||||
* @param <T> 对象类型
|
||||
*/
|
||||
public class PoolPartition<T> implements ObjectPool<T> {
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
private final PoolConfig config;
|
||||
private final ObjectFactory<T> objectFactory;
|
||||
|
||||
private BlockingQueue<Poolable<T>> queue;
|
||||
private BlockingQueue<PartitionPoolable<T>> queue;
|
||||
// 记录对象总数(包括借出对象)
|
||||
private int total;
|
||||
|
||||
public PoolPartition(PoolConfig config, BlockingQueue<Poolable<T>> queue, ObjectFactory<T> objectFactory) {
|
||||
/**
|
||||
* 构造
|
||||
*
|
||||
* @param config 池配置
|
||||
* @param queue 阻塞队列类型
|
||||
* @param objectFactory 对象工厂,用于管理对象创建、检查和销毁
|
||||
*/
|
||||
public PoolPartition(final PoolConfig config, final BlockingQueue<PartitionPoolable<T>> queue, final ObjectFactory<T> objectFactory) {
|
||||
this.config = config;
|
||||
this.queue = queue;
|
||||
this.objectFactory = objectFactory;
|
||||
@ -43,11 +71,26 @@ public class PoolPartition<T> implements Closeable {
|
||||
total = minSize;
|
||||
}
|
||||
|
||||
public Poolable<T> borrowObject() {
|
||||
@SuppressWarnings("resource")
|
||||
@Override
|
||||
public PartitionPoolable<T> borrowObject() {
|
||||
// 非阻塞获取
|
||||
Poolable<T> poolable = this.queue.poll();
|
||||
PartitionPoolable<T> poolable = this.queue.poll();
|
||||
if (null != poolable) {
|
||||
return poolable;
|
||||
// 检查对象是否可用
|
||||
if (this.objectFactory.validate(poolable.getRaw())) {
|
||||
// 检查是否超过最长空闲时间
|
||||
final long maxIdle = this.config.getMaxIdle();
|
||||
if (maxIdle > 0 && (System.currentTimeMillis() - poolable.getLastBorrow()) <= maxIdle) {
|
||||
poolable.setLastBorrow(System.currentTimeMillis());
|
||||
return poolable;
|
||||
}
|
||||
}
|
||||
|
||||
// 对象不可用,销毁之
|
||||
free(poolable);
|
||||
// 继续借,而不扩容
|
||||
return borrowObject();
|
||||
}
|
||||
|
||||
// 扩容
|
||||
@ -61,24 +104,41 @@ public class PoolPartition<T> implements Closeable {
|
||||
}
|
||||
|
||||
// 扩容成功,继续借对象
|
||||
// 如果线程1扩容,但是被线程2借走,则继续递归扩容获取对象,直到获取到或全部借走为止
|
||||
return borrowObject();
|
||||
}
|
||||
|
||||
/**
|
||||
* 归还对象
|
||||
*
|
||||
* @param obj 归还的对象
|
||||
* @param poolable 归还的对象
|
||||
* @return this
|
||||
*/
|
||||
public PoolPartition<T> returnObject(final Poolable<T> obj) {
|
||||
try {
|
||||
this.queue.put(obj);
|
||||
} catch (InterruptedException e) {
|
||||
throw new HutoolException(e);
|
||||
@SuppressWarnings("resource")
|
||||
@Override
|
||||
public PoolPartition<T> returnObject(final Poolable<T> poolable) {
|
||||
// 检查对象可用性
|
||||
if (this.objectFactory.validate(poolable.getRaw())) {
|
||||
try {
|
||||
this.queue.put((PartitionPoolable<T>) poolable);
|
||||
} catch (final InterruptedException e) {
|
||||
throw new HutoolException(e);
|
||||
}
|
||||
} else {
|
||||
// 对象不可用
|
||||
free(poolable);
|
||||
}
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* 扩容并填充对象池队列<br>
|
||||
* 如果传入的扩容大小大于可用大小(即扩容大小加现有大小大于最大大小,则实际扩容到最大)
|
||||
*
|
||||
* @param increaseSize 扩容大小
|
||||
* @return 实际扩容大小,0表示已经达到最大,未成功扩容
|
||||
*/
|
||||
public synchronized int increase(int increaseSize) {
|
||||
if (increaseSize + total > config.getMaxSize()) {
|
||||
increaseSize = config.getMaxSize() - total;
|
||||
@ -107,15 +167,21 @@ public class PoolPartition<T> implements Closeable {
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取对象总数,包括借出对象数
|
||||
*
|
||||
* @return 对象数
|
||||
*/
|
||||
@Override
|
||||
public int getTotal() {
|
||||
return this.total;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getIdleCount() {
|
||||
return this.queue.size();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getActiveCount() {
|
||||
return getTotal() - getIdleCount();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void close() throws IOException {
|
||||
this.queue.forEach(this::free);
|
||||
@ -123,11 +189,23 @@ public class PoolPartition<T> implements Closeable {
|
||||
this.queue = null;
|
||||
}
|
||||
|
||||
protected Poolable<T> createPoolable() {
|
||||
/**
|
||||
* 创建{@link PartitionPoolable}
|
||||
*
|
||||
* @return {@link PartitionPoolable}
|
||||
*/
|
||||
protected PartitionPoolable<T> createPoolable() {
|
||||
return new PartitionPoolable<>(objectFactory.create(), this);
|
||||
}
|
||||
|
||||
private Poolable<T> waitingPoll() {
|
||||
/**
|
||||
* 从队列中取出头部的对象,如果队列为空,则等待<br>
|
||||
* 等待的时间取决于{@link PoolConfig#getMaxWait()},小于等于0时一直等待,否则等待给定毫秒数
|
||||
*
|
||||
* @return 取出的池对象
|
||||
* @throws HutoolException 中断异常
|
||||
*/
|
||||
private PartitionPoolable<T> waitingPoll() throws HutoolException {
|
||||
final long maxWait = this.config.getMaxWait();
|
||||
try {
|
||||
if (maxWait <= 0) {
|
||||
|
@ -0,0 +1,100 @@
|
||||
/*
|
||||
* Copyright (c) 2023. looly(loolly@aliyun.com)
|
||||
* Hutool is licensed under Mulan PSL v2.
|
||||
* You can use this software according to the terms and conditions of the Mulan PSL v2.
|
||||
* You may obtain a copy of Mulan PSL v2 at:
|
||||
* https://license.coscl.org.cn/MulanPSL2
|
||||
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
|
||||
* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
|
||||
* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
|
||||
* See the Mulan PSL v2 for more details.
|
||||
*/
|
||||
|
||||
package org.dromara.hutool.core.pool;
|
||||
|
||||
import org.dromara.hutool.core.collection.ListUtil;
|
||||
import org.dromara.hutool.core.io.IoUtil;
|
||||
import org.dromara.hutool.core.pool.partition.PartitionObjectPool;
|
||||
import org.dromara.hutool.core.pool.partition.PartitionPoolConfig;
|
||||
import org.junit.jupiter.api.Assertions;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import java.util.ArrayList;
|
||||
|
||||
public class PartitionObjectPoolTest {
|
||||
|
||||
public ObjectPool<StringBuilder> init() {
|
||||
final PartitionPoolConfig config = (PartitionPoolConfig) PartitionPoolConfig.of()
|
||||
.setPartitionSize(2)
|
||||
.setMinSize(2)
|
||||
.setMaxSize(20)
|
||||
.setMaxIdle(5000)
|
||||
.setMaxWait(100);
|
||||
|
||||
final ObjectFactory<StringBuilder> factory = new ObjectFactory<StringBuilder>() {
|
||||
@Override
|
||||
public StringBuilder create() {
|
||||
return new StringBuilder();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void destroy(final StringBuilder o) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean validate(final StringBuilder o) {
|
||||
return true;
|
||||
}
|
||||
};
|
||||
return new PartitionObjectPool<>(config, factory);
|
||||
}
|
||||
|
||||
@Test
|
||||
void borrowObjectTest() {
|
||||
final ObjectPool<StringBuilder> pool = init();
|
||||
// 初始4个对象
|
||||
Assertions.assertEquals(4, pool.getTotal());
|
||||
|
||||
for (int i = 0; i < 20; i++) {
|
||||
final Poolable<StringBuilder> obj = pool.borrowObject();
|
||||
obj.getRaw().append("hutool");
|
||||
}
|
||||
// 池1的2个+池2借出的20个,合计22个
|
||||
Assertions.assertEquals(22, pool.getTotal());
|
||||
Assertions.assertEquals(20, pool.getActiveCount());
|
||||
Assertions.assertEquals(2, pool.getIdleCount());
|
||||
|
||||
IoUtil.closeQuietly(pool);
|
||||
}
|
||||
|
||||
@Test
|
||||
void borrowAndReturnObjectTest() {
|
||||
final ObjectPool<StringBuilder> pool = init();
|
||||
// 初始4个对象
|
||||
Assertions.assertEquals(4, pool.getTotal());
|
||||
|
||||
final ArrayList<Poolable<StringBuilder>> borrowed = ListUtil.of();
|
||||
for (int i = 0; i < 10; i++) {
|
||||
final Poolable<StringBuilder> obj = pool.borrowObject();
|
||||
obj.getRaw().append("hutool");
|
||||
borrowed.add(obj);
|
||||
}
|
||||
// 池1的2个+池2借出的10个,合计12个
|
||||
Assertions.assertEquals(12, pool.getTotal());
|
||||
Assertions.assertEquals(10, pool.getActiveCount());
|
||||
Assertions.assertEquals(2, pool.getIdleCount());
|
||||
|
||||
// 全部归还
|
||||
for (final Poolable<StringBuilder> obj : borrowed) {
|
||||
pool.returnObject(obj);
|
||||
}
|
||||
|
||||
// 池1的2个+池2的10个,合计12个
|
||||
Assertions.assertEquals(12, pool.getTotal());
|
||||
Assertions.assertEquals(0, pool.getActiveCount());
|
||||
// 全部空闲
|
||||
Assertions.assertEquals(12, pool.getIdleCount());
|
||||
|
||||
IoUtil.closeQuietly(pool);
|
||||
}
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user