Java并发对象池?

我尝试将外部非线程安全库集成到我的Web项目中; 我发现为每个客户端线程创建此对象的实例太昂贵了。

因此,我想创建一个具有以下属性的对象池。

  1. 动态对象创建时,动态创建池中的对象,而不是在构造函数中创建它们。 池最初为空,当客户端线程获取资源对象时,池可以按需创建新资源。 一旦创建的对象的数量达到池的大小; 然后将阻止新的客户端线程,并等待其他线程回收资源。
  2. 池应该是公平的,公平性确保第一个要求的线程是获得的第一个线程; 否则有些线程可能会永远等待。

我该怎么做? 如果有一个有效的例子,我将不胜感激。

这个问题和解决方案总结自https://www.dbtsai.com/blog/2013/java-concurrent-dynamic-object-pool-for-non-thread-safe-objects-using-blocking-queue/

并发对象池可以由Java并发包中的阻塞队列构建,而ArrayBlockingQueue也支持我们需要的公平性。 在此实现中,我使用ReentrantLock来控制是否可以在池中创建新对象。 因此,在非动态创建模式中,即在构造函数中创建所有对象,此锁将始终被锁定; 在动态创建模式中,每次只能创建一个对象,所以如果有另一个线程获取该对象,它将从pool.take()获取阻止删除的对象,并等待新的可用对象队列中的资源。

public abstract class ResourcePool {     private final BlockingQueue pool;     private final ReentrantLock lock = new ReentrantLock();     private int createdObjects = 0;     private int size;      protected ResourcePool(int size) {         this(size, false);     }      protected ResourcePool(int size, Boolean dynamicCreation) {         // Enable the fairness; otherwise, some threads         // may wait forever.         pool = new ArrayBlockingQueue<>(size, true);         this.size = size;         if (!dynamicCreation) {             lock.lock();         }     }      public Resource acquire() throws Exception {         if (!lock.isLocked()) {             if (lock.tryLock()) {                 try {                     ++createdObjects;                     return createObject();                 } finally {                     if (createdObjects < size) lock.unlock();                 }             }         }         return pool.take();     }      public void recycle(Resource resource) throws Exception {         // Will throws Exception when the queue is full,         // but it should never happen.         pool.add(resource);     }      public void createPool() {         if (lock.isLocked()) {             for (int i = 0; i < size; ++i) {                 pool.add(createObject());                 createdObjects++;             }         }     }      protected abstract Resource createObject(); } 

在以下示例中,有5个客户端线程同时在资源池中获取两个DataTimeFormat对象,这些客户端线程总共将执行30次计算。

  class DataTimeFormatResourcePool extends ResourcePool {    DataTimeFormatResourcePool(int size, Boolean dynamicCreation) {        super(size, dynamicCreation);        createPool();    }    @Override    protected SimpleDateFormat createObject() {        return new SimpleDateFormat("yyyyMMdd");    }    public Date convert(String input) throws Exception {        SimpleDateFormat format = acquire();        try {            return format.parse(input);        } finally {            recycle(format);        }    } } public class ResourcePoolExample {    public static void main(String args[]) {        final DataTimeFormatResourcePool pool = new DataTimeFormatResourcePool(2, true);        Callable task = new Callable() {            @Override            public Date call() throws Exception {                return pool.convert("20130224");            }        };        ExecutorService exec = Executors.newFixedThreadPool(5);        List> results = new ArrayList<>();        for (int i = 0; i < 30; i++) {            results.add(exec.submit(task));        }        exec.shutdown();        try {            for (Future result : results) {                System.out.println(result.get());            }        } catch (Exception ex) {            ex.printStackTrace();        }    } }