Как безопасно закрыть GenericKeyedObjectPool?

В моем приложении есть GenericKeyedObjectPool . Я могу закрыть его методом close, но как мне ждать, пока клиенты вернут (и пул уничтожит) каждый заимствованный объект в пул?

Мне нужно что-то вроде ExecutorService.awaitTermination.


person palacsint    schedule 13.11.2012    source источник


Ответы (2)


Создайте оболочку для GenericKeyedObjectPool с требуемым методом awaitTermination. Вы можете проверить вызовы close и returnObject и уменьшить защелку, если пул закрыт и каждый объект был возвращен (= общее количество экземпляров, заимствованных из этого пула, равно нулю).

public final class ListenablePool<K, V> {

    private final GenericKeyedObjectPool<K, V> delegate;

    private final CountDownLatch closeLatch = new CountDownLatch(1);

    private final AtomicBoolean closed = new AtomicBoolean();

    public ListenablePool(final KeyedPoolableObjectFactory<K, V> factory) {
        this.delegate = new GenericKeyedObjectPool<K, V>(factory);
    }

    public V borrowObject(final K key) throws Exception {
        return delegate.borrowObject(key);
    }

    public void returnObject(final K key, final V obj) throws Exception {
        try {
            delegate.returnObject(key, obj);
        } finally {
            countDownIfRequired();
        }
    }

    private void countDownIfRequired() {
        if (closed.get() && delegate.getNumActive() == 0) {
            closeLatch.countDown();
        }
    }

    public void close() throws Exception {
        try {
            delegate.close();
        } finally {
            closed.set(true);
            countDownIfRequired();
        }
    }

    public void awaitTermination() throws InterruptedException {
        closeLatch.await();
    }

    public void awaitTermination(final long timeout, final TimeUnit unit) 
            throws InterruptedException {
        closeLatch.await(timeout, unit);
    }

    public int getNumActive() {
        return delegate.getNumActive();
    }

    // other delegate methods
}
person palacsint    schedule 13.11.2012

Вы должны быть в безопасности, просто закрыв его, не дожидаясь возврата всех объектов.

Из документации GenericKeyedObjectPool .html#close():

Закрывает бассейн. После того, как пул будет закрыт, заимствованиеObject() завершится с ошибкой IllegalStateException, но returnObject(Object) и invalidateObject(Object) продолжат работать, а возвращенные объекты будут уничтожены при возврате.

person Andrey    schedule 13.11.2012
comment
Спасибо за ответ! Объекты в пуле представляют собой соединения с базой данных/сетью, поэтому для удаленных систем удобнее закрыть их, если это возможно. Во всяком случае, это заставило меня задуматься о том, что я, возможно, не захочу вечно ждать объект, который может никогда не быть возвращен. - person palacsint; 15.11.2012