2009-07-16 6 views
9

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

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

какой-либо причине вы делаете это сами? Apache Commons Pool делает это с полки. – skaffman

+3

Что делает ApacheCommonsPool, что блокировкаQueue не делает? Он втягивает большую библиотеку, чтобы определить большой набор «стандартных» интерфейсов, когда java.util.concurrent.BlockingQueue уже поддерживает все определенные операции. – bhan

+0

@ skaffman вы можете помочь http://stackoverflow.com/questions/43860936/create-objects-in-genericobjectpool – Tony

ответ

0

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

Редактировать: я не читал код, который тщательно. Поэтому я немного отредактировал сообщение. :(

2

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

13

Как уже отмечалось, одна ограниченная 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); 
    } 
} 

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

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

+0

Приятный и чистый пример - но мой выбор состоял бы в том, чтобы сделать абстрактную форму класса пула, а не финальную, и добавить абстрактную " T createExpensiveObject() ". – mindas

+0

Просто понял, что мое предложение не будет работать, так как ваше решение статически инициализирует буфер внутри конструктора. Попробует изменить ваш пример для способности создавать дорогие объекты по требованию. – mindas

1

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

5

Несколько модифицированный пример sjlee; позволяя создавать дорогостоящие объекты по требованию. Мой случай не требовал блокировки, поэтому я заменил его неблокирующим типом очереди. В качестве выгоды вам не нужно иметь дело с 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 
    } 
} 
+0

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

+0

Похоже, вы пропустили ключевой элемент, о котором идет речь: ** basic **. Здесь мы не разрабатываем полномасштабное решение; иногда ** basic ** покрывает все потребности. – mindas

3

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

0

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

От here

/** 
* 
* @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()); 
     } 
    } 
} 
Смежные вопросы