BlockingQueue与Semaphore

时间:2012-09-04 15:50:21

标签: java multithreading concurrency semaphore blockingqueue

如果我们想要实现资源池,例如数据库连接池。您将使用哪个并发集合? BlockingQueueSemaphore

对于BlockingQueue,就像生产者 - 消费者设计模式一样,生产者将所有连接放在队列上,消费者将从队列中获取下一个可用连接。

对于Semaphore,您将信号量指定为池大小,并获取许可,直到达到池大小并等待其中任何一个释放许可并将资源放回池中。

哪一个更简单,更容易?什么是我们只能使用一个而不是其他的情景?

3 个答案:

答案 0 :(得分:13)

BlockingQueue更简单,因为它也会跟踪Connections /资源。

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有助于跟踪免费资源并确保没有太多可用资源。它是线程安全的,无需显式锁定。

如果使用信号量,则仍需要将资源存储在集合中(使信号量变为冗余;)

答案 1 :(得分:0)

无论如何,许多阻塞队列都使用信号量实现(并且可能是互斥/ futex / CS)。我使用阻塞队列进行对象存储很多 - 一旦你有一个有效的阻塞队列,为什么还要为对象池使用其他东西呢?

答案 2 :(得分:0)

对于高级连接池,我可能不会使用。正如@PeterLawrey指出的那样,BlockingQueue对于最初存在所有资源的简单池最有意义。但是,如果你想做更复杂的事情,比如按需创建资源,那么你很可能需要额外的并发结构。在这种情况下,您最有可能最终使用简单的同步块或Lock。