package com.resare.concurrent; import java.util.ArrayList; import java.util.List; import java.util.concurrent.LinkedBlockingQueue; /** * Works like a LinkedBlockingQueue using the put() and take() methods but * with an additional priority integer parameter. The elemnt returned from * take() will honor the priority in such a way that all elements of a lower * priority will be returned before any elemens of a higher priority. * */ public class MultiPrioQueue { private List> qs; private int lowestNonEmpty = Integer.MAX_VALUE; public MultiPrioQueue(int maxPriority) { qs = new ArrayList>(); for (int i = 0; i < maxPriority + 1; i++) { qs.add(new LinkedBlockingQueue()); } } public void put(E element, int priority) { synchronized (this) { if (priority < 0 || priority > qs.size() - 1) { throw new IllegalArgumentException("parameter priority must be " + "between 0 and " + (qs.size() -1)); } LinkedBlockingQueue q = qs.get(priority); try { q.put(element); } catch (InterruptedException e) { throw new Error(e); } if (lowestNonEmpty == Integer.MAX_VALUE) { this.notify(); } if (priority < lowestNonEmpty) { lowestNonEmpty = priority; } } } public E take() { synchronized (this) { try { if(lowestNonEmpty == Integer.MAX_VALUE) { this.wait(); } LinkedBlockingQueue q = qs.get(lowestNonEmpty); E e = q.take(); if (q.isEmpty()) { lowestNonEmpty = findNextNonEmpty(lowestNonEmpty); } return e; } catch (InterruptedException e) { throw new Error(e); } } } private int findNextNonEmpty(int lowestNonEmpty) { for (int i = lowestNonEmpty; i < qs.size(); i++) { if (!qs.get(i).isEmpty()) { return i; } } return Integer.MAX_VALUE; } }