Ограниченный PriorityBlockingQueue

PriorityBlockingQueue неограниченно, но мне нужен к связанному он так или иначе. Что лучший способ состоит в том, чтобы достигнуть этого?

Для получения информации, ограниченный PriorityBlockingQueue будет использоваться в a ThreadPoolExecutor.

NB: ограниченным, я не хочу выдавать Исключение, если это происходит, я хочу поместить объект в очередь и затем сократить его на основе ее приоритетного значения. Там какой-либо хороший путь состоит в том, чтобы сделать эту штуку сокращения?

16
задан nanda 26 February 2010 в 12:59
поделиться

4 ответа

На самом деле я бы не стал создавать подклассы. Хотя я не могу сейчас составить пример кода, я бы предложил версию паттерна декоратора.

Создайте новый класс и реализуйте интерфейсы, реализуемые интересующим вас классом: PriorityBlockingQueue. Я обнаружил следующие интерфейсы, используемые этим классом:

Serializable, Iterable<E>, Collection<E>, BlockingQueue<E>, Queue<E>

В конструкторе класса примите PriorityBlockingQueue в качестве параметра конструктора.

Затем реализуйте все методы, требуемые интерфейсами, через экземпляры PriorityblockingQueue. Добавьте любой код, необходимый для того, чтобы сделать его Bounded.

Вот быстрая диаграмма, которую я составил в Violet UML:

Диаграмма класса BoundedPriorityblockingQueue http://theopensourceu.com/wp-content/uploads/2010/03/BoundedPriorityBlockingQueue.png

12
ответ дан 30 November 2019 в 22:24
поделиться

Насколько я знаю, я бы создал подкласс и перезаписал метод put, чтобы обеспечить это. Если это произойдет, создайте исключение или сделайте то, что кажется подходящим.

Что-то вроде:

public class LimitedPBQ extends PriorityBlockingQueue {

    private int maxItems;
    public LimitedPBQ(int maxItems){
        this.maxItems = maxItems;
    }

    @Override
    public boolean offer(Object e) {
        boolean success = super.offer(e);
        if(!success){
            return false;
        } else if (this.size()>maxItems){
            // Need to drop last item in queue
            // The array is not guaranteed to be in order, 
            // so you should sort it to be sure, even though Sun's Java 6 
            // version will return it in order
            this.remove(this.toArray()[this.size()-1]);
        }
        return true;
    }
}

Edit: и добавляет, и помещает предложение вызова, поэтому переопределения должно быть достаточно

Edit 2: теперь должен удалить последний элемент, если он превышает maxItems. Однако может быть более элегантный способ сделать это.

2
ответ дан 30 November 2019 в 22:24
поделиться

Если порядок выполнения Runnables, которые вы хотите выполнить, не строгий (как есть: может случиться, что некоторые задачи с более низким приоритетом будут выполнены, несмотря на существование задач с более высоким приоритетом), то я бы предложил следующее, что сводится к периодическому уменьшению размера PriorityQueue:

if (queue.size() > MIN_RETAIN * 2){
    ArrayList<T> toRetain = new ArrayList<T>(MIN_RETAIN);
    queue.drainTo(toRetain, MIN_RETAIN);
    queue.clear();
    for (T t : toRetain){
      queue.offer(t);
    }
}

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

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

0
ответ дан 30 November 2019 в 22:24
поделиться

Посмотрите на ForwardingQueue из Google Collections API. Для семантики блокировки можно использовать Semaphore.

-1
ответ дан 30 November 2019 в 22:24
поделиться
Другие вопросы по тегам:

Похожие вопросы: