这个基本的Java对象池工作吗?

这个基本的Java对象池工作吗?,java,concurrency,object-pooling,Java,Concurrency,Object Pooling,以下基本对象池是否工作?我有一个基于相同想法的更复杂的方法(即同时维护信号量和阻塞队列)。我的问题是-我需要信号量和阻塞队列吗?我不需要做任何同步,对吗 import java.util.Collection; import java.util.concurrent.ArrayBlockingQueue; import java.util.concurrent.BlockingQueue; import java.util.concurrent.Semaphore; public final

以下基本对象池是否工作?我有一个基于相同想法的更复杂的方法(即同时维护信号量和阻塞队列)。我的问题是-我需要信号量和阻塞队列吗?我不需要做任何同步,对吗

import java.util.Collection;
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.Semaphore;

public final class Pool<T> {

    private final BlockingQueue<T> objects;
    private final Semaphore permits;

    public Pool(Collection<? extends T> objects) {
        // we have as many permits as objects in our pool:
        this.permits = new Semaphore(objects.size());
        this.objects = new ArrayBlockingQueue<T>(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();
    }
}
import java.util.Collection;
导入java.util.concurrent.ArrayBlockingQueue;
导入java.util.concurrent.BlockingQueue;
导入java.util.concurrent.Semaphore;
公开期末班{
私有最终阻塞队列对象;
专用最终信号量许可证;

公共池(集合也许你应该检查对象是否存在,这是我唯一拥有的东西


编辑:我没有仔细阅读代码。因此我对文章进行了一些编辑。(

使用take()代替poll(),使用put()代替add())。然后,信号量是完全冗余的,因此您可以将其删除。但是,是的,这看起来不错。

正如前面所指出的,仅使用有界阻塞队列就足够了。例如,以下代码将执行您想要的操作:

import java.util.Collection;
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.BlockingQueue;

public final class Pool<T> {

    private final BlockingQueue<T> objects;

    public Pool(Collection<? extends T> objects) {
        this.objects = new ArrayBlockingQueue<T>(objects.size(), false, objects);
    }

    public T borrow() throws InterruptedException {
        return this.objects.take();
    }

    public void giveBack(T object) throws InterruptedException {
        this.objects.put(object);
    }
}
import java.util.Collection;
导入java.util.concurrent.ArrayBlockingQueue;
导入java.util.concurrent.BlockingQueue;
公开期末班{
私有最终阻塞队列对象;

公共游泳池(收集当您从ArrayBlockingQueue中获取条目时,ArrayBlockingQueue创建一个对象是毫无价值的。因此,您的池实际上不会保存对象。只有当您的对象创建成本很高时,它才有帮助。

一个稍微修改过的sjlee示例;允许按需创建昂贵的对象。我的案例不需要任何阻塞工具因此,我将其替换为非阻塞队列类型。作为一个优点,不需要处理中断异常

import java.util.Collection;
import java.util.Queue;
import java.util.concurrent.ConcurrentLinkedQueue;

public abstract class ObjectPool<T> {

    private final Queue<T> objects;

    public ObjectPool() {
        this.objects = new ConcurrentLinkedQueue<T>();
    }

    public ObjectPool(Collection<? extends T> objects) {
        this.objects = new ConcurrentLinkedQueue<T>(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
    }
}
import java.util.Collection;
导入java.util.Queue;
导入java.util.concurrent.ConcurrentLinkedQueue;
公共抽象类对象池{
私有最终队列对象;
公共对象池(){
this.objects=新的ConcurrentLinkedQueue();
}

public ObjectPool(Collection可能使用堆栈而不是队列?这样就有机会获取仍位于处理器缓存中的对象。

对于后者,这里有一个更简单、更完整的池。 它比最简单的好,而且很简单

/**
* 
*@见简单池
*/
抽象静态类对象池
{
专用ConcurrentLinkedQueue池;
专用ScheduledExecutorService executorService;
/**
*创建池。
*
*@param minIdle池中驻留的最小对象数
*/
公共对象池(最终int-minIdle)
{
//初始化池
初始化(minIdle);
}
/**
*创建池。
*
*@param minIdle池中驻留的最小对象数
*@param maxIdle池中驻留的最大对象数
*@param validationInterval用于定期检查单独线程中的minIdle/maxIdle条件的时间(秒)。
*当对象数小于minIdle时,将创建缺少的实例。
*当对象数大于maxIdle时,将删除太多实例。
*/
公共对象池(最终int-minIdle、最终int-maxIdle、最终long-validationInterval)
{
//初始化池
初始化(minIdle);
//在单独的线程中检查池条件
executorService=Executors.newSingleThreadScheduledExecutor();
executorService.scheduleWithFixedDelay(新的Runnable()
{
@凌驾
公开募捐
{
int size=pool.size();
如果(尺寸<迷你)
{
int sizetobeaded=minIdle-size;
对于(int i=0;i最大空闲)
{
int sizeToBeRemoved=size-maxIdle;
对于(int i=0;i
您自己这么做的原因是什么?Apache Commons Pool现成就做了。ApacheCommonsPool提供了blockingQueue不提供的功能是什么?它引入了一个大型库来定义一组大型的“标准”当java.util.concurrent.BlockingQueue已经支持所有已定义的操作时的接口。@skaffman您可以帮助创建一个漂亮且清晰的示例-但我的选择是将池类抽象化而不是最终化,并添加一个abs
/**
 * 
 * @see <a href=http://www.javacodegeeks.com/2013/08/simple-and-lightweight-pool-implementation.html>simple pool</>
 */
abstract static class ObjectPool<T>
{
    private ConcurrentLinkedQueue<T> 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<T>();

        for (int i = 0; i < minIdle; i++)
        {
            pool.add(createObject());
        }
    }
}