Работает ли этот базовый пул объектов Java? - PullRequest
9 голосов
/ 16 июля 2009

Работает ли следующий базовый пул объектов? У меня есть более сложный, основанный на той же идее (то есть поддержание и семафора и BlockingQueue) У меня вопрос - нужен ли мне и Семафор, и BlockingQueue? Я прав, что мне не нужно выполнять какую-либо синхронизацию?

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();
    }
}

Ответы [ 7 ]

15 голосов
/ 16 июля 2009

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

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);
    }
}

Кроме того, вы можете рассмотреть возможность поддержки синхронизированной версии loan () с использованием BlockingQueue.poll ().

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

6 голосов
/ 28 июля 2009

Несколько модифицированный пример Сджли; позволяет создавать дорогие объекты по запросу. В моем случае не требовалось никаких средств блокировки, поэтому я заменил это на неблокирующий тип очереди. Как преимущество, нет необходимости иметь дело с InterruptedExceptions.

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
    }
}
3 голосов
/ 02 ноября 2009

Может быть, использовать стек вместо очереди? Это дает возможность получить объект, который все еще находится в кэше процессора.

2 голосов
/ 16 июля 2009

Используйте take () вместо poll () и put () вместо add (). Семафор тогда полностью избыточен, так что вы можете просто избавиться от него. Но да, это выглядит хорошо.

1 голос
/ 17 июля 2009

Ничего не стоит, что ArrayBlockingQueue создает объект, когда вы берете из него запись. Таким образом, ваш пул на самом деле не будет сохранять объекты. Это может помочь, только если ваши объекты стоят дорого.

0 голосов
/ 12 марта 2015

Вот еще один простой и полный пул для последнего. Это лучше, чем самое простое, и это просто.

С здесь

/**
 * 
 * @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());
        }
    }
}
0 голосов
/ 16 июля 2009

Может быть, вы должны проверить, что объекты существуют, это единственное, что у меня есть.

Редактировать: Я не читал этот код внимательно. Так что я немного редактировал пост. (

...