Advanced   Java   Services LinkedList und PriorityQueue Back Next Up Home


Nonblocking Queues

Es gibt drei nicht blockierende Queues, Linkedlist, PriorityQueue und ConcurrentLinkedQueue.



Übersicht über nonblocking Queues
Bounded FIFO LIFO Head = Longest time element Head = Least element Insert at tail Retrieve from head Permits null Thread safe
LinkedList xxxx
PriorityQueue x
ConcurrentLinkedQueue x xxx x


LinkedList

Die Klasse LinkedList fällt aus der Reihe, weil sie bereits in 1.2 eingeführt worden ist und nachträglich so erweitert wurde, daß sie das Interface Queue (1.5) und das Interface Deque (1.6) implementiert. Aus diesem Grund leitet sich LinkedList auch nicht von AbstractQueue ab, sondern direkt von AbstractSequentialList (1.2). Linkedlist ist die einzige Queue, die das Interface List implementiert hat.





PriorityQueue

Aus der API

An unbounded priority queue based on a priority heap. The elements of the priority queue are ordered according to their natural ordering, or by a Comparator provided at queue construction time, depending on which constructor is used. A priority queue does not permit null elements. A priority queue relying on natural ordering also does not permit insertion of non-comparable objects (doing so may result in ClassCastException).

The head of this queue is the least element with respect to the specified ordering. If multiple elements are tied for least value, the head is one of those elements -- ties are broken arbitrarily. The queue retrieval operations poll, remove, peek, and element access the element at the head of the queue.

A priority queue is unbounded, but has an internal capacity governing the size of an array used to store the elements on the queue. It is always at least as large as the queue size. As elements are added to a priority queue, its capacity grows automatically. The details of the growth policy are not specified.

This class and its iterator implement all of the optional methods of the Collection and Iterator interfaces. The Iterator provided in method iterator() is not guaranteed to traverse the elements of the priority queue in any particular order. If you need ordered traversal, consider using Arrays.sort(pq.toArray()).

Note that this implementation is not synchronized. Multiple threads should not access a PriorityQueue instance concurrently if any of the threads modifies the queue. Instead, use the thread-safe PriorityBlockingQueue class.

Implementation note: this implementation provides O(log(n)) time for the enqueing and dequeing methods (offer, poll, remove() and add); linear time for the remove(Object) and contains(Object) methods; and constant time for the retrieval methods (peek, element, and size).


Erklärung

Es können nur Elemente aufgenommen werden, deren Klasse das Interface Comparable implementiert hat oder zu der es eine Vergleichsklasse (Comparator) gibt. Eine PriorityQueue verwendet beim Aufnehmen von Elementen die Methode compareTo() oder im zweiten Fall die Methode compare() um das alphabetische kleinste Element an die Spitze (Head) zu bringen. Egal welche Methode zum Entnehmen eines Elements verwendet wird, es kann immer nur das Headelement entnommen werden. Jede Entnahme löst einen Vergleich aus, da dann das Headelement aktualisiert werden muß. Die PriorityQueue ist keine blockierende Queue, die Methoden put() und take() existieren hier (noch) nicht. Ist die Queue leer, so werfen die Methoden entweder eine Exception oder sie liefern null.


Beispiel

Das einfache Beispiel zeigt die Aufrufe der Vergleichsfunktion bei der Aufnahme und Entnahme von Elementen.

Es wird eine Klasse MyString angelegt, die das Interface Comparable implementiert und eine Meldung ausgibt falls die Methode compareTo() gerufen wird.

Auf diese Weise wird der Algorithmus sichtbar mit dem die PriorityQueue arbeitet. Die Queue ist also keineswegs vollständig geordnet, nur das Headelemnent wird an die erste Stelle gesetzt.

class MyString implements Comparable<MyString>
{
   String string;

   public MyString(String string)
   {
      this.string = string;
   }

   @Override
   public int compareTo(MyString ob)
   {
      System.out.println("compareTo: " + this.string + "  " + ob.string);
      return this.string.compareTo(ob.toString());
   }

   @Override
   public String toString()
   {
      return string;
   }
}

Main nimmt vier Elemente auf und entfernt diese nacheinander. Jedesmal werden die verbleibenden Elemente aufgelistet und man sieht die Aufrufe von compareTo().

public class PriorityQueueDemo_01
{
   public static void main(String[] args)
   {
      PriorityQueue<MyString> pq = new PriorityQueue<>();

      System.out.println("Aufzunehmendes Element: eins" );
      pq.add(new MyString("eins"));
      System.out.println("Enthaltene Elemente: " + pq);
      System.out.println("Aufzunehmendes Element: zwei" );
      pq.add(new MyString("zwei"));
      System.out.println("Enthaltene Elemente: " + pq);
      System.out.println("Aufzunehmendes Element: drei" );
      pq.add(new MyString("drei"));
      System.out.println("Enthaltene Elemente: " + pq);
      System.out.println("Aufzunehmendes Element: vier" );
      pq.add(new MyString("vier"));
      System.out.println("Enthaltene Elemente: " + pq);

      System.out.println("--------------------------------");

      System.out.println("head = " + pq.element());
      System.out.println("poll = " + pq.poll());  // holt das Headelement raus
      // bestimmt den neuen Head, bevor der alte Head geliefert wird
      System.out.println("head = " + pq.element());
      System.out.println("Enthaltene Elemente: " + pq);

      System.out.println("--------------------------------");

      System.out.println("head = " + pq.element());
      System.out.println("poll = " + pq.poll());
      System.out.println("head = " + pq.element());
      System.out.println("Enthaltene Elemente: " + pq);

      System.out.println("--------------------------------");

      System.out.println("head = " + pq.element());
      System.out.println("poll = " + pq.poll());
      System.out.println("head = " + pq.element());
      System.out.println("Enthaltene Elemente:" + pq);

      System.out.println("--------------------------------");

      System.out.println("head = " + pq.element());
      System.out.println("poll = " + pq.poll());
      //System.out.println("head = " + pq.element());   // NoSuchElementException
      System.out.println("Enthaltene Elemente: " + pq);
   }
}

Konsolausgabe

Aufzunehmendes Element: eins
Enthaltene Elemente: [eins]
Aufzunehmendes Element: zwei
compareTo: zwei  eins
Enthaltene Elemente: [eins, zwei]
Aufzunehmendes Element: drei
compareTo: drei  eins
Enthaltene Elemente: [drei, zwei, eins]
Aufzunehmendes Element: vier
compareTo: vier  zwei
compareTo: vier  drei
Enthaltene Elemente: [drei, vier, eins, zwei]
--------------------------------
head = drei
compareTo: vier  eins
compareTo: zwei  eins
poll = drei
head = eins
Enthaltene Elemente: [eins, vier, zwei]
--------------------------------
head = eins
compareTo: zwei  vier
poll = eins
head = vier
Enthaltene Elemente: [vier, zwei]
--------------------------------
head = vier
poll = vier
head = zwei
Enthaltene Elemente:[zwei]
--------------------------------
head = zwei
poll = zwei
Enthaltene Elemente: []






Valid XHTML 1.0 Strict top Back Next Up Home