Пул объектов (Object pool)


Обратите внимание, что вы не ограничены созданием только одного объекта. Есть также техника создания ограниченного пула объектов. В такой ситуации, однако, вы можете встретиться с проблемой разделения объектов пула. Если это ваш выбор, вы можете создать решение, вовлекающее проверку периода использования разделяемых объектов.

Как пример, предлагаю базу данных. Коммерческие базы данных часто ограничивают число соединений, которые вы можете использовать одновременно. Ниже приведена реализация, которая использует пул объектов, для управления соединениями. Прежде всего, основная концепция управления пулом объектов реализована в виде отдельного класса:

//: :PoolManager.java
package singleton;

import java.util.*;

public class PoolManager {
  
private static class PoolItem {
     
boolean inUse = false;
      Object item;
     
      PoolItem
(Object item) {
        
this.item = item;
     
}
   }
  
  
private ArrayList items = new ArrayList();
  
  
public void add(Object item) {
     
items.add(new PoolItem(item));
  
}
  
  
static class EmptyPoolException extends Exception {
   }
  
  
public Object get() throws EmptyPoolException {
     
for (int i = 0; i < items.size(); i++) {
        
PoolItem pitem = (PoolItem) items.get(i);
        
if (pitem.inUse == false) {
           
pitem.inUse = true;
           
return pitem.item;
        
}
      }
     
// :
     
throw new EmptyPoolException();
     
// return null; //
  
}
  
  
public void release(Object item) {
     
for (int i = 0; i < items.size(); i++) {
        
PoolItem pitem = (PoolItem) items.get(i);
        
if (item == pitem.item) {
           
pitem.inUse = false;
           
return;
        
}
      }
     
throw new RuntimeException(item + " not found");
  
}
}
// /:~

//: singleton:ConnectionPoolDemo.java
package singleton;

import junit.framework.*;

interface Connection {
  
Object get();
  
  
void set(Object x);
}

class ConnectionImplementation implements Connection {
  
public Object get() {
     
return null;
  
}
  
  
public void set(Object s) {
   }
}

class ConnectionPool { // Синглетон
  
private static PoolManager pool = new PoolManager();
  
  
public static void addConnections(int number) {
     
for (int i = 0; i < number; i++)
        
pool.add(new ConnectionImplementation());
  
}
  
  
public static Connection getConnection()
        
throws PoolManager.EmptyPoolException {
     
return (Connection) pool.get();
  
}
  
  
public static void releaseConnection(Connection c) {
     
pool.release(c);
  
}
}

public class ConnectionPoolDemo extends TestCase {
  
static {
     
ConnectionPool.addConnections(5);
  
}
  
  
public void test() {
     
Connection c = null;
     
try {
        
c = ConnectionPool.getConnection();
     
}
     
catch (PoolManager.EmptyPoolException e) {
        
throw new RuntimeException(e);
     
}
     
c.set(new Object());
      c.get
();
      ConnectionPool.releaseConnection
(c);
  
}
  
  
public void test2() {
     
Connection c = null;
     
try {
        
c = ConnectionPool.getConnection();
     
}
     
catch (PoolManager.EmptyPoolException e) {
        
throw new RuntimeException(e);
     
}
     
c.set(new Object());
      c.get
();
      ConnectionPool.releaseConnection
(c);
  
}
  
  
public static void main(String args[]) {
     
junit.textui.TestRunner.run(ConnectionPoolDemo.class);
  
}
}
// /:~

Упражнения

  1. Добавьте тестирование модуля ConnectionPoolDemo.java, чтобы продемонстрировать проблему, когда клиент может не освободить соединение, а продолжать использовать его.