BlockingQueue против семафора

Если мы хотим реализовать пул ресурсов, такой как пул соединений с базой данных. Какую параллельную коллекцию вы будете использовать? BlockingQueue или Semaphore ?

Для BlockingQueue, как и в шаблоне проектирования производитель-потребитель, производитель поместит все соединения в очередь, а потребитель возьмет следующее доступное соединение из очереди.

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

Какой из них проще и легче? и каков сценарий, когда мы можем использовать только один, но не другой?


person peter    schedule 04.09.2012    source источник
comment
вы не будете размещать запросы в BlockingQueue, вы поместите соединения в BlockingQueue.   -  person jtahlborn    schedule 04.09.2012
comment
вы правы. позвольте мне обновить это   -  person peter    schedule 04.09.2012


Ответы (3)


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

e.g.

public abstract class ResourcePool<Resource> {
    private final BlockingQueue<Resource> free;

    protected ResourcePool(int freeLimit) {
        free = new ArrayBlockingQueue<>(freeLimit);
    }

    public Resource acquire() {
        Resource resource = free.poll();
        return resource == null ? create() : resource;
    }

    public void recycle(Resource resource) {
        if (!free.offer(resource))
            close(resource);
    }

    protected abstract Resource create();

    protected abstract void close(Resource resource);
}

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

Если вы используете семафор, вам все равно нужно хранить ресурсы в коллекции (что делает семафор избыточным;)

person Peter Lawrey    schedule 04.09.2012
comment
Действительно, очень хороший вопрос - как вернуть соединения (когда они больше не используются)? - person assylias; 04.09.2012
comment
@assylias Я добавил пример. - person Peter Lawrey; 04.09.2012

В любом случае, многие блокирующие очереди реализованы с семафорами (и, возможно, с мьютексом/фьютексом/CS). Я часто использую очереди блокировки для хранения объектов — если у вас есть работающая очередь блокировки, зачем использовать что-то еще для пула объектов?

person Martin James    schedule 04.09.2012

Для расширенного пула соединений я бы, вероятно, не использовал ни того, ни другого. Как отмечает @PeterLawrey, BlockingQueue лучше всего подходит для простого пула, в котором изначально существуют все ресурсы. однако, если вы хотите сделать что-то более сложное, например создать ресурсы по запросу, вам, скорее всего, потребуются дополнительные конструкции параллелизма. в этом случае вы, скорее всего, в конечном итоге будете использовать простой синхронизированный блок или блокировку.

person jtahlborn    schedule 04.09.2012