这个基本的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 extends T> 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 extends T> 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。 🙁