Design Patterns教程-对象池设计模式
对象池模式表示“重用创建代价高的对象”。
基本上,对象池是一个包含指定数量对象的容器。当对象从池中取出时,它在放回之前不会在池中可用。池中的对象具有生命周期:创建、验证和销毁。
池有助于更好地管理可用资源。许多使用示例尤其是在应用程序服务器中,例如数据源池、线程池等。
对象池设计模式的优点
- 它显著提高了应用程序的性能。
- 在初始化类实例的速率较高的情况下,它最有效。
- 它管理连接并提供重用和共享连接的方法。
- 它还可以提供可以创建的最大对象数量的限制。
使用场景
- 当应用程序需要创建代价高的对象时。例如:需要打开大量数据库连接时,创建新连接需要较长时间,数据库服务器将超载。
- 当多个客户端在不同时间需要相同资源时。
注意:对象池设计模式通常用于服务器的 Web 容器中,用于创建线程池和数据源池以处理请求。
对象池模式的示例
通过给定的 UML 图来理解示例。
对象池模式的 UML
实现上述 UML:
步骤 1
创建一个用于创建多个对象的 ObjectPool 类。
文件:ObjectPool.java
import java.util.concurrent.ConcurrentLinkedQueue;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;
public abstract class ObjectPool<T> {
/*
pool 实现基于 java.util.concurrent 包中的 ConcurrentLinkedQueue。
ConcurrentLinkedQueue 是一个基于链接节点的线程安全队列。
因为队列遵循 FIFO 技术(先进先出)。
*/
private ConcurrentLinkedQueue<T> pool;
/*
ScheduledExecutorService 在一个单独的线程中启动一个特殊任务,并定期观察池中的最小和最大对象数量。
当对象数量小于最小值时,将创建缺失的实例。
当对象数量大于最大值时,将移除过多的实例。
这有时对于池中内存消耗对象的平衡很有用。
*/
private ScheduledExecutorService executorService;
/*
创建池。
@param minObjects: 池中存在的最小对象数量
*/
public ObjectPool(final int minObjects) {
// 初始化池
initialize(minObjects);
}
/*
创建池。
@param minObjects: 池中存在的最小对象数量。
@param maxObjects: 池中存在的最大对象数量。
@param validationInterval: 用于定期检查最小对象/最大对象条件的时间(以秒为单位)。
当对象数量小于最小对象数量时,将创建缺失的实例。
当对象数量大于最大对象数量时,将移除过多的实例。
*/
public ObjectPool(final int minObjects, final int maxObjects, final long validationInterval) {
// 初始化池
initialize(minObjects);
// 在单独的线程中检查池条件
executorService = Executors.newSingleThreadScheduledExecutor();
executorService.scheduleWithFixedDelay(new Runnable() {
@Override
public void run() {
int size = pool.size();
if (size < minObjects) {
int sizeToBeAdded = minObjects - size;
for (int i = 0; i < sizeToBeAdded; i++) {
pool.add(createObject());
}
} else if (size > maxObjects) {
int sizeToBeRemoved = size - maxObjects;
for (int i = 0; i < sizeToBeRemoved; i++) {
pool.poll();
}
}
}
}, validationInterval, validationInterval, TimeUnit.SECONDS);
}
/*
从池中获取下一个空闲对象。如果池中没有对象,将创建一个新对象并返回给调用此方法的对象。
@return T 借用的对象
*/
public T borrowObject() {
T object;
if ((object = pool.poll()) == null) {
object = createObject();
}
return object;
}
/*
将对象返回到池中。
@param object 要返回的对象
*/
public void returnObject(T object) {
if (object == null) {
return;
}
this.pool.offer(object);
}
/*
关闭此池。
*/
public void shutdown() {
if (executorService != null) {
executorService.shutdown();
}
}
/*
创建一个新对象。
@return T 新对象
*/
protected abstract T createObject();
private void initialize(final int minObjects) {
pool = new ConcurrentLinkedQueue<T>();
for (int i = 0; i < minObjects; i++) {
pool.add(createObject());
}
}
} // ObjectPool 类结束
步骤 2
创建一个将由 ExportingTask 类使用的 ExportingProcess 类。
文件:ExportingProcess.java
public class ExportingProcess {
private long processNo;
public ExportingProcess(long processNo) {
this.processNo = processNo;
// 将来在此处执行一些昂贵的调用/任务
// .........
System.out.println("Object with process no. " + processNo + " was created");
}
public long getProcessNo() {
return processNo;
}
} // ExportingProcess 类结束
步骤 3
创建一个将使用 ExportingProcess 和 ObjectPool 类的 ExportingTask 类。
文件:ExportingTask.java
public class ExportingTask implements Runnable {
private ObjectPool<ExportingProcess> pool;
private int threadNo;
public ExportingTask(ObjectPool<ExportingProcess> pool, int threadNo) {
this.pool = pool;
this.threadNo = threadNo;
}
public void run() {
// 从池中获取一个对象
ExportingProcess exportingProcess = pool.borrowObject();
System.out.println("Thread " + threadNo + ": Object with process no. "
+ exportingProcess.getProcessNo() + " was borrowed");
// 将来可以在此处执行一些操作
// .........
// 将 ExportingProcess 实例返回到池中
pool.returnObject(exportingProcess);
System.out.println("Thread " + threadNo + ": Object with process no. "
+ exportingProcess.getProcessNo() + " was returned");
}
} // ExportingTask 类结束
步骤 4
创建一个 ObjectPoolDemo 类。
文件:ObjectPoolDemo.java
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicLong;
public class ObjectPoolDemo {
private ObjectPool<ExportingProcess> pool;
private AtomicLong processNo = new AtomicLong(0);
public void setUp() {
// 创建一个 ExportingProcess 类型的对象池。
/* 参数:
1) 池中存在的最小特殊 ExportingProcess 实例数量 = 4
2) 池中存在的最大特殊 ExportingProcess 实例数量 = 10
3) 在单独的线程中定期检查最小对象/最大对象条件的时间(以秒为单位)= 5。
-->当 ExportingProcess 实例的数量小于最小对象数量时,将创建缺失的实例。
-->当 ExportingProcess 实例的数量大于最大对象数量时,将移除过多的实例。
-->如果验证间隔为负值,则不会在单独的线程中定期检查最小对象/最大对象条件。
这些边界将被忽略。
*/
pool = new ObjectPool<ExportingProcess>(4, 10, 5) {
protected ExportingProcess createObject() {
// 创建一个需要一些时间来创建的测试对象
return new ExportingProcess(processNo.incrementAndGet());
}
};
}
public void tearDown() {
pool.shutdown();
}
public void testObjectPool() {
ExecutorService executor = Executors.newFixedThreadPool(8);
// 在单独的线程中执行 8 个任务
executor.execute(new ExportingTask(pool, 1));
executor.execute(new ExportingTask(pool, 2));
executor.execute(new ExportingTask(pool, 3));
executor.execute(new ExportingTask(pool, 4));
executor.execute(new ExportingTask(pool, 5));
executor.execute(new ExportingTask(pool, 6));
executor.execute(new ExportingTask(pool, 7));
executor.execute(new ExportingTask(pool, 8));
executor.shutdown();
try {
executor.awaitTermination(30, TimeUnit.SECONDS);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
public static void main(String args[]) {
ObjectPoolDemo op = new ObjectPoolDemo();
op.setUp();
op.testObjectPool();
op.tearDown();
}
} // ObjectPoolDemo 类结束