这个基本的Java对象池有用吗?

以下基本对象池是否有效? 我有一个更复杂的基于相同的想法(即保持信号量和BlockingQueue)。 我的问题是 – 我需要Semaphore和BlockingQueue吗? 我是对的,我不需要做任何同步吗?

import java.util.Collection; import java.util.concurrent.ArrayBlockingQueue; import java.util.concurrent.BlockingQueue; import java.util.concurrent.Semaphore; public final class Pool { private final BlockingQueue objects; private final Semaphore permits; public Pool(Collection objects) { // we have as many permits as objects in our pool: this.permits = new Semaphore(objects.size()); this.objects = new ArrayBlockingQueue(objects.size(), false, objects); } public T borrow() { this.permits.acquireUninterruptibly(); // we have a permit, so there must be one in there: return this.objects.poll(); } public void giveBack(T object) { this.objects.add(object); this.permits.release(); } } 

正如已经指出的那样,单独一个有界的BlockingQueue就足够了。 例如,以下代码将执行您想要的操作:

 import java.util.Collection; import java.util.concurrent.ArrayBlockingQueue; import java.util.concurrent.BlockingQueue; public final class Pool { private final BlockingQueue objects; public Pool(Collection objects) { this.objects = new ArrayBlockingQueue(objects.size(), false, objects); } public T borrow() throws InterruptedException { return this.objects.take(); } public void giveBack(T object) throws InterruptedException { this.objects.put(object); } } 

此外,您可能需要考虑使用BlockingQueue.poll()支持borrow()的定时版本。

如果您没有有界阻塞队列数据结构,则可以在任何数据结构之上施加信号量以创建线程安全和绑定行为。

一个有点修改的sjlee的例子; 允许按需创建昂贵的对象。 我的情况不需要任何阻塞function,因此我用非阻塞队列类型替换了它。 作为一个好处,没有必要处理InterruptedExceptions。

 import java.util.Collection; import java.util.Queue; import java.util.concurrent.ConcurrentLinkedQueue; public abstract class ObjectPool { private final Queue objects; public ObjectPool() { this.objects = new ConcurrentLinkedQueue(); } public ObjectPool(Collection objects) { this.objects = new ConcurrentLinkedQueue(objects); } public abstract T createExpensiveObject(); public T borrow() { T t; if ((t = objects.poll()) == null) { t = createExpensiveObject(); } return t; } public void giveBack(T object) { this.objects.offer(object); // no point to wait for free space, just return } } 

也许使用堆栈而不是队列? 这样就有可能获得仍然位于处理器缓存中的对象。

使用take()而不是poll(),并使用put()而不是add()。 信号量完全是多余的,所以你可以摆脱它。 但是,这看起来不错。

当你从中获取一个条目时,ArrayBlockingQueue创建一个对象并不值得。 所以你的池实际上不会保存对象。 它只有在你的对象创建成本昂贵时才有用。

也许你应该检查对象是否存在,这是我唯一拥有的东西。

编辑:我没有仔细阅读代码。 所以我稍微编了一下post。 🙁

这是后者的一个更简单和完整的池。 它比最简单的更好,而且很简单。

从这里开始

 /** * * @see simple pool */ abstract static class ObjectPool { private ConcurrentLinkedQueue pool; private ScheduledExecutorService executorService; /** * Creates the pool. * * @param minIdle minimum number of objects residing in the pool */ public ObjectPool(final int minIdle) { // initialize pool initialize(minIdle); } /** * Creates the pool. * * @param minIdle minimum number of objects residing in the pool * @param maxIdle maximum number of objects residing in the pool * @param validationInterval time in seconds for periodical checking of minIdle / maxIdle conditions in a separate thread. * When the number of objects is less than minIdle, missing instances will be created. * When the number of objects is greater than maxIdle, too many instances will be removed. */ public ObjectPool(final int minIdle, final int maxIdle, final long validationInterval) { // initialize pool initialize(minIdle); // check pool conditions in a separate thread executorService = Executors.newSingleThreadScheduledExecutor(); executorService.scheduleWithFixedDelay(new Runnable() { @Override public void run() { int size = pool.size(); if (size < minIdle) { int sizeToBeAdded = minIdle - size; for (int i = 0; i < sizeToBeAdded; i++) { pool.add(createObject()); } } else if (size > maxIdle) { int sizeToBeRemoved = size - maxIdle; for (int i = 0; i < sizeToBeRemoved; i++) { pool.poll(); } } } }, validationInterval, validationInterval, TimeUnit.SECONDS); } /** * Gets the next free object from the pool. If the pool doesn't contain any objects, * a new object will be created and given to the caller of this method back. * * @return T borrowed object */ public T borrowObject() { T object; if ((object = pool.poll()) == null) { object = createObject(); } return object; } /** * Returns object back to the pool. * * @param object object to be returned */ public void returnObject(T object) { if (object == null) { return; } this.pool.offer(object); } /** * Shutdown this pool. */ public void shutdown() { if (executorService != null) { executorService.shutdown(); } } /** * Creates a new object. * * @return T new object */ protected abstract T createObject(); private void initialize(final int minIdle) { pool = new ConcurrentLinkedQueue(); for (int i = 0; i < minIdle; i++) { pool.add(createObject()); } } }