codestory

Die Anleitung zu Java PriorityBlockingQueue

Folge uns auf unserer fanpage, um jedes Mal benachrichtigt zu werden, wenn es neue Artikel gibt. Facebook

1- PriorityBlockingQueue

PriorityBlockingQueue<E> ist eine Klasse, die eine Warteschlange mit nach Priorität sortierten Elementen darstellt, ähnlich der Klasse PriorityQueue<E>. Der Unterschied besteht darin, dass es die Interface BlockingQueue<E> implementiert, also über zusätzliche Funktionen verfügt, die von dieser Interface angegeben werden.
Sie sollten sich den Artikel über die Interface BlockingQueue vorsehen, um mehr Details über die Funktionen dieser Interface mit grundlegenden Beispielen zu erfahren.

public class PriorityBlockingQueue<E> extends AbstractQueue<E>
             implements BlockingQueue<E>, java.io.Serializable
Die Eigenschaften von PriorityBlockingQueue:
  • Eine Warteschlange mit unbegrenzter Kapazität.
  • Doppelte Elemente sind zulässig, aber die Elemente null sind nicht zulässig.
  • Die Elemente werden nach einem mitgelieferten Comparator aufsteigend sortiert oder die Elemente werden in ihrer natürlichen Reihenfolge sortiert (je nach verwendetem Konstruktor).
  • PriorityBlockingQueue und sein Iterator unterstützen alle optionalen Methoden, die in den Interface Collection und Iterator angegeben sind.
Grundsätzlich verwaltet PriorityBlockingQueue ein internes Array zum Speichern von Elementen, das durch ein neues Array ersetzt werden kann, wenn die Anzahl der Elemente der Warteschlange steigt.
Das von der Iterator-Methode erhaltene Iterator-Objekt und das von der Spliterator-Methode erhaltene Spliterator-Objekt garantieren nicht, dass die Elemente dieser Warteschlange in einer bestimmten Reihenfolge durchlaufen werden. Wenn Sie möchten, sollten Sie Arrays.sort(queue.toArray()) verwenden.
Zum Beispiel:
PriorityBlockingQueue_traverse_ex1.java

// Create a queue that sorts its elements in natural order.
BlockingQueue<String> queue = new PriorityBlockingQueue<>();
queue.add("Rose");
queue.add("Lotus");
queue.add("Jasmine");
queue.add("Sunflower");
queue.add("Daisy");

System.out.println(queue); // [Daisy, Jasmine, Lotus, Sunflower, Rose] (Not ordered)
String[] array = new String[queue.size()];
queue.toArray(array);
Arrays.sort(array);
for(String flower: array)  {
    System.out.println(flower);
}
Output:

[Daisy, Jasmine, Lotus, Sunflower, Rose]
Daisy
Jasmine
Lotus
Rose
Sunflower

2- Constructors


public PriorityBlockingQueue()
public PriorityBlockingQueue(int initialCapacity)  
public PriorityBlockingQueue(int initialCapacity, Comparator<? super E> comparator)  
public PriorityBlockingQueue(Collection<? extends E> c) 
Sehen Sie die detaillierten Erläuterungen für jeden Konstruktor unten.

3- Zum Beispiel: 

Sehen Sie  auch den Artikel BockingQueue für grundlegende Beispiele. 
Bekanntlich ist das Modell Producer/Consumer ein gutes Beispiel für die Verwendung der Interface BlockingQueue . Von Herstellern erstellte Produkte werden einer Warteschlange hinzugefügt, bevor sie von den Verbrauchern übernommen werden. In einigen Fällen ist die Verwendung einer Prioritätswarteschlange erforderlich. Produkte mit kurzer Haltbarkeit müssen beispielsweise eine höhere Priorität haben, um bald von den Verbrauchern konsumiert zu werden.
Sehen wir uns ein einfaches Beispiel an:
Die Klasse Product repräsentiert Produkte mit Namen und Informationen zur Haltbarkeit:
Product.java

package org.o7planning.priorityblockingqueue.ex;

public class Product {
    private String name;
    private int shelfLife;

    public Product(String name, int shelfLife) {
        this.name = name;
        this.shelfLife = shelfLife;
    }  
    public int getShelfLife() {
        return shelfLife;
    }
    @Override
    public String toString() {
        return this.name + ":" + this.shelfLife;
    }
}
Die Klasse ProductComparator wird verwendet, um Objekte Product zu vergleichen. Das Produkt mit der längeren Haltbarkeit gilt als größer. Das Produkt mit der geringsten Haltbarkeit steht an der Spitze der Warteschlange.
ProductComparator.java

package org.o7planning.priorityblockingqueue.ex;

import java.util.Comparator;

public class ProductComparator implements Comparator<Product> {

    @Override
    public int compare(Product o1, Product o2) {
        return o1.getShelfLife() - o2.getShelfLife();
    }
}
  • TODO Link?
Producer.java

package org.o7planning.priorityblockingqueue.ex;

import java.util.Random;
import java.util.concurrent.BlockingQueue;

public class Producer implements Runnable {  
    private final String producerName;
    private final BlockingQueue<Product> queue;
    private final int delay; // Seconds

    public Producer(String producerName, int delay, BlockingQueue<Product> q) {
        this.producerName = producerName;
        this.delay = delay;
        this.queue = q;
    }
    @Override
    public void run() {
        try {
            while (true) {
                Thread.sleep(this.delay * 1000); // 'delay' seconds.
                Product newProduct = this.produce();
                System.out.println("\n#" + this.producerName + " >> New Product: " + newProduct);
                this.queue.put(newProduct);
                // Printed results may not be sorted (***):
                System.out.println("  Current products in queue: " + this.queue + " (***)");
            }
        } catch (InterruptedException ex) {
        }
    }
    private Product produce() {
        int shelfLife = new Random().nextInt(3) + 3;
        return new Product("Apple", shelfLife);
    }
}
Consumer.java

package org.o7planning.priorityblockingqueue.ex;

import java.util.concurrent.BlockingQueue;

public class Consumer implements Runnable {
    private String consumerName;
    private final BlockingQueue<Product> queue;

    public Consumer(String consumerName, BlockingQueue<Product> q) {
        this.consumerName = consumerName;
        this.queue = q;
    }
    @Override
    public void run() {
        try {
            while (true) {
                this.consume(queue.take());
            }
        } catch (InterruptedException ex) {
        }
    }
    // Need 1 seconds to consume a product.
    private void consume(Product x) throws InterruptedException {
        System.out.println(" --> " + this.consumerName + " >> Consuming: " + x);
        Thread.sleep(1 * 1000); // 1 seconds.
    }
}
Setup.java

package org.o7planning.priorityblockingqueue.ex;

import java.util.Comparator;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.PriorityBlockingQueue;

public class Setup {
    public static void main(String[] args) {
        // Comparator
        Comparator<Product> comparator = new ProductComparator();
        // Create a PriorityBlockingQueue with a capacity of 100.
        BlockingQueue<Product> queue = new PriorityBlockingQueue<Product>(100, comparator);
        queue.add(new Product("Banana", 5));
        queue.add(new Product("Banana", 2));
        queue.add(new Product("Banana", 7));
        queue.add(new Product("Banana", 3));
        queue.add(new Product("Banana", 1));  
        
        Producer producer1 = new Producer("Producer 01", 2, queue);
        Producer producer2 = new Producer("Producer 02", 3, queue);
        
        Consumer consumer1 = new Consumer("Consumer 01", queue);
        Consumer consumer2 = new Consumer("Consumer 02", queue);
        Consumer consumer3 = new Consumer("Consumer 03", queue);

        // Starting Producer threads
        new Thread(producer1).start();
        new Thread(producer2).start();
        // Starting Consumer threads
        new Thread(consumer1).start();
    }
}
(***) Hinweis: In diesem Beispiel verwenden wir die Methode System.out.println(queue), um alle Elemente der Warteschlange auszudrucken. Diese Methode garantiert jedoch nicht die Reihenfolge der Elemente.
Output:

--> Consumer 01 >> Consuming: Banana:1
--> Consumer 01 >> Consuming: Banana:2

#Producer 01 >> New Product: Apple:4
Current products in queue: [Banana:3, Apple:4, Banana:7, Banana:5] (***)
--> Consumer 01 >> Consuming: Banana:3

#Producer 02 >> New Product: Apple:3
Current products in queue: [Apple:3, Apple:4, Banana:7, Banana:5] (***)
--> Consumer 01 >> Consuming: Apple:3

#Producer 01 >> New Product: Apple:5
Current products in queue: [Apple:4, Banana:5, Banana:7, Apple:5] (***)
--> Consumer 01 >> Consuming: Apple:4
--> Consumer 01 >> Consuming: Apple:5

#Producer 02 >> New Product: Apple:4
Current products in queue: [Apple:4, Banana:7, Banana:5] (***)

#Producer 01 >> New Product: Apple:5
Current products in queue: [Apple:4, Apple:5, Banana:5, Banana:7] (***)
--> Consumer 01 >> Consuming: Apple:4
--> Consumer 01 >> Consuming: Apple:5
...

4- PriorityBlockingQueue()


public PriorityBlockingQueue()
Erstellen Sie eine PriorityBlockingQueue mit standardmäßiger Anfangskapazität (11). Die Elemente dieser Warteschlange werden in ihrer natürlichen Reihenfolge sortiert, was erfordert, dass alle Elemente Objekte der Interface Comparable sein müssen.
  • TODO Link?

5- PriorityBlockingQueue(int)


public PriorityBlockingQueue(int initialCapacity)  
Erstellt eine PriorityBlockingQueue mit der angegebenen Anfangskapazität. Die Elemente dieser Warteschlange werden in ihrer natürlichen Reihenfolge sortiert, was erfordert, dass alle Elemente Objekte der Interface Comparable sind.
  • TODO Link?

6- PriorityBlockingQueue(int, Comparator)


public PriorityBlockingQueue(int initialCapacity, Comparator<? super E> comparator) 
Erstellt eine PriorityBlockingQueue mit der angegebenen Anfangskapazität und einem bereitgestellten Comparator zum Sortieren ihrer Elemente. Wenn der Comparator null ist, wird die natürliche Reihenfolge der Elemente verwendet, was erfordert, dass alle Elemente Objekte der Interface Comparable sein müssen.

7- PriorityBlockingQueue(Collection)


public PriorityBlockingQueue(Collection<? extends E> c)
Erstellt eine PriorityBlockingQueue, die alle Elemente der angegebenen Collection enthält.
Wenn diese angegebene Collection ein SortedSet oder eine PriorityQueue ist, verwendet diese PriorityBlockingQueue denselben Comparator. Andernfalls wird die natürliche Reihenfolge der Elemente verwendet, was erfordert, dass alle Elemente Objekte der Interface Comparable sein müssen.

8- Methods

Die Methoden, die von der Interface BockingQueue<E> geerbt werden:

void put(E e) throws InterruptedException;
boolean offer(E e, long timeout, TimeUnit unit) throws InterruptedException;
E take() throws InterruptedException;
E poll(long timeout, TimeUnit unit) throws InterruptedException;
int remainingCapacity();
int drainTo(Collection<? super E> c);  
int drainTo(Collection<? super E> c, int maxElements);
Lesen Sie den Artikel zu BlockingQueue, um zu erfahren, wie Sie die oben genannten Methoden verwenden.
Methoden, die von der Interface Queue<E> geerbt werden:

boolean add(E e);
boolean offer(E e);
E remove();
E poll();
E element();
E peek();
Die Methoden, die von der Interface Collection<E> geerbt werden:

int size();
boolean isEmpty();
boolean contains(Object o);
Iterator<E> iterator();
Object[] toArray();
<T> T[] toArray(T[] a);
boolean add(E e);
boolean remove(Object o);
boolean containsAll(Collection<?> c);  
boolean addAll(Collection<? extends E> c);
boolean removeAll(Collection<?> c);
boolean retainAll(Collection<?> c);
void clear();  
boolean equals(Object o);
int hashCode();

default <T> T[] toArray(IntFunction<T[]> generator)  
default boolean removeIf(Predicate<? super E> filter)
default Spliterator<E> spliterator()  
default Stream<E> stream()  
default Stream<E> parallelStream()
  • TODO Link?