Ограниченная очередь блокирования


Может кто-то пожалуйста, проверьте этот код для меня? Я не реализованы все методы для простоты.

/**
 * Implements a blocking bounded queue from a given non-blocking unbounded queue implementation
 */
abstract class DerivedQueue<E> implements Queue<E>
{
    DerivedQueue(Queue<E> queue, int size)
    {
        if(queue==null | size <0)
        {
            throw new RuntimeException("Bad Input");
        }
        fQueue = queue;
        fSize = size;
    }



    Queue<E> fQueue;
    int fSize;
    int fCnt;

    @Override
    public boolean addAll(Collection<? extends E> arg0)
    {
        return false;
    }

    @Override
    public boolean isEmpty()
    {
        return (fCnt==0);
    }

    public E remove()
    {
        if(fCnt==0)
        {
            try
            {
                wait();
            }
            catch (InterruptedException e)
            {
                throw new RuntimeException("Waiting thread was interrupted during remove with msg:",e);
            }
        }


        E elem =  fQueue.remove();
        fCnt--;
        notifyAll();
        return elem;
    }

    @Override
    public boolean add(E elem)
    {
        if(fCnt == fSize)
        {
            try
            {
                wait();
            }
            catch (InterruptedException e)
            {
                throw new RuntimeException("Waiting thread was interrupted during remove with msg:",e);
            }
        }

        return fQueue.add(elem);
    }

}

Открытые вопросы:

  1. Бы вызов notifyAll() приводят к несколько ожидающих потоков проверки в то время как() состояние одновременно, и, следовательно, есть вероятность, что до того, пока не будет удовлетворен, 2 темы уже это вызывает outOfBound исключение? Или все-таки методы должны быть помечены синхронизированы на всех, и вместо этого я могу использовать синхронизированный блок для чтения или записи части массива при проведении проверок ограничения и ожидания остаются несинхронизированными?

  2. Есть ли способ, чтобы уведомить именно только потоки потребителей (ожидание в взять) или только продюсером (ввод в ожидании) потоков в этом примере? notifyAll уведомляет всех из них.



Комментарии
5 ответов

Эта проблема кричит "семафор".

У семафора, количество которых соответствует количеству слотов в очереди. Enqueuers уменьшить семафор. Dequeuers инкрементировать его. Это эффективно ограничивает количество узлов в очереди к некоторого максимума, а именно начальное значение семафора.

Кроме того вы можете иметь различные семафор представляет собой число элементов в очереди. В этом случае dequeuers декремента и инкремента enqueuers. Для этого, первоначальная стоимость равна нулю. Это позволяет dequeuers блокировать до тех пор, пока товар есть в наличии.

5
ответ дан 30 июня 2011 в 06:06 Источник Поделиться

В моем классе оценки переменных всегда должны быть определены первых - еще до того, как конструктор. Другой вопрос: почему ваши переменные с префиксом Ф? Переименовать на что-то менее запутанный вместо. Особенно японская жена и fCnt довольно близко друг к другу. (Предполагая, что параметр maxsize и currentSize).

2
ответ дан 28 июня 2011 в 09:06 Источник Поделиться

Ваша реализация не ориентирована на многопотоковое исполнение: представьте, что очередь пуста, и несколько потоков, которые хотите удалить элемент ожидания. Тогда элемент будет добавлен и все ожидающие потоки будут уведомлены. Затем они все пробуют без дальнейших тестов , чтобы удалить элемент, который будет работать только для первого потока, следующая приведет к потере. Тот же сценарий по несколько потоков, ожидающих, чтобы добавить.

Так что либо исправить проблему или добавьте комментарий с "не ориентирована на многопотоковое исполнение" предупреждение.

2
ответ дан 30 июня 2011 в 06:06 Источник Поделиться

Я видел еще две проблема с приведенный выше код:


  1. Эти отсутствует приращение к fCurrrentCnt++ в Добавить способ.

  2. Это приведет в тупик, если попытаться вызвать удалить сначала, а потом добавить. Оба будут ждать друг друга.

1
ответ дан 13 июля 2011 в 08:07 Источник Поделиться

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

Смотрите также: Эффективная Java, 2-е издание, пункт 47: знать и использовать библиотеки

В любом случае, это не кажется полностью потокобезопасным. В fCurrrentCnt поле в пустой способ чтения без каких-либо синхронизированный блок.


[...] синхронизацию не влияет, если обе операции чтения и записи будут синхронизированы.

От эффективная Java 2-е издание, пункт 66: синхронизировать доступ к разделяемым изменяемым данным.

0
ответ дан 28 октября 2012 в 09:10 Источник Поделиться