对象池模式表示“重用创建代价高的对象”

基本上,对象池是一个包含指定数量对象的容器。当对象从池中取出时,它在放回之前不会在池中可用。池中的对象具有生命周期:创建、验证和销毁。

池有助于更好地管理可用资源。许多使用示例尤其是在应用程序服务器中,例如数据源池、线程池等。

对象池设计模式的优点

  • 它显著提高了应用程序的性能。
  • 在初始化类实例的速率较高的情况下,它最有效。
  • 它管理连接并提供重用和共享连接的方法。
  • 它还可以提供可以创建的最大对象数量的限制。

使用场景

  • 当应用程序需要创建代价高的对象时。例如:需要打开大量数据库连接时,创建新连接需要较长时间,数据库服务器将超载。
  • 当多个客户端在不同时间需要相同资源时。

注意:对象池设计模式通常用于服务器的 Web 容器中,用于创建线程池和数据源池以处理请求。

对象池模式的示例

通过给定的 UML 图来理解示例。

对象池模式的 UML

6-1.jpg

实现上述 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 类结束

输出

6-2.jpg

标签: Design Patterns, Design Patterns教程, 设计模式, 软件设计, 结构型模式, 行为型模式, 单例模式, 工厂模式, 观察者模式, 中介者模式, 访问者模式