Java双端队列,传输队列

114 阅读1分钟

「这是我参与11月更文挑战的第30天,活动详情查看:2021最后一次更文挑战

Java双端队列

双端队列或deque扩展队列以允许元件从两端插入和移除。

Deque 类的实例表示双端队列。 Deque 接口扩展了 Queue 接口。

它声明了方便所有操作的其他方法对于头部以及尾部的队列。它可以用作FIFO队列或LIFO队列。

ArrayDeque和LinkedList类是Deque接口的两个实现类。

ArrayDeque 类由数组支持,而 LinkedList 类由链表支持。

如果您使用Deque作为堆栈,则应该使用 ArrayDeque 作为 Deque 实现。

如果使用 Deque 作为FIFO队列, LinkedList

以下代码显示如何使用 Deque 作为FIFO队列。

import java.util.Deque;
import java.util.LinkedList;

public class Main {
  public static void main(String[] args) {
    Deque<String> deque = new LinkedList<>();
    deque.addLast("Oracle");
    deque.offerLast("Java");
    deque.offerLast("CSS");
    deque.offerLast("XML");

    System.out.println("Deque: " + deque);

    // remove elements from the Deque until it is empty
    while (deque.peekFirst() != null) {
      System.out.println("Head  Element: " + deque.peekFirst());
      deque.removeFirst();
      System.out.println("Removed one  element from  Deque");
      System.out.println("Deque: " + deque);
    }

    // the Deque is empty. Try to call its peekFirst(),
    // getFirst(), pollFirst() and removeFirst() methods
    System.out.println("deque.isEmpty(): " + deque.isEmpty());

    System.out.println("deque.peekFirst(): " + deque.peekFirst());
    System.out.println("deque.pollFirst(): " + deque.pollFirst());

    String str = deque.getFirst();
    System.out.println("deque.getFirst(): " + str);
    str = deque.removeFirst();
    System.out.println("deque.removeFirst(): " + str);

  }
}

上面的代码生成以下结果。

例子

以下代码显示如何使用Deque作为堆栈(或LIFO队列)。

import java.util.ArrayDeque;
import java.util.Deque;

public class Main {
  public static void main(String[] args) {
    // Create a Deque and use it as stack
    Deque<String> deque = new ArrayDeque<>();
    deque.push("Oracle");
    deque.push("HTML");
    deque.push("CSS");
    deque.push("XML");

    System.out.println("Stack: " + deque);

    // remove all elements from the Deque
    while (deque.peek() != null) {
      System.out.println("Element at  top:  " + deque.peek());
      System.out.println("Popped: " + deque.pop());
      System.out.println("Stack: " + deque);
    }

    System.out.println("Stack is  empty:  " + deque.isEmpty());
  }
}

上面的代码生成以下结果。

**

\

Java传输队列

传输队列扩展阻塞队列。

生产者使用 TransferQueue 的 transfer(E element)方法将元素传递给消费者。

当生产者调用传递(E元素)方法时,它等待直到消费者获取其元素。 tryTransfer()方法提供了该方法的非阻塞和超时版本。

getWaitingConsumerCount()方法返回等待消费者的数量。

如果有一个等待消费者, hasWaitingConsumer()方法返回true; 否则,返回false。 LinkedTransferQueue 是 TransferQueue 接口的实现类。 它提供了一个无界的 TransferQueue 。

以下代码显示如何使用 TransferQueue 。

import java.util.concurrent.LinkedTransferQueue;
import java.util.concurrent.TransferQueue;
import java.util.concurrent.atomic.AtomicInteger;

class TQProducer extends Thread {
  private String name;
  private TransferQueue<Integer> tQueue;
  private AtomicInteger sequence;
  public TQProducer(String name, TransferQueue<Integer> tQueue,
      AtomicInteger sequence) {
    this.name = name;
    this.tQueue = tQueue;
    this.sequence = sequence;
  }

  @Override
  public void run() {
    while (true) {
      try {
        Thread.sleep(4000);
        int nextNum = this.sequence.incrementAndGet();
        if (nextNum % 2 == 0) {
          System.out.format("%s:  Enqueuing: %d%n", name, nextNum);
          tQueue.put(nextNum); // Enqueue
        } else {
          System.out.format("%s: Handing  off: %d%n", name, nextNum);
          System.out.format("%s: has  a  waiting  consumer: %b%n", name,
              tQueue.hasWaitingConsumer());
          tQueue.transfer(nextNum); // A hand off
        }
      } catch (InterruptedException e) {
        e.printStackTrace();
      }
    }
  }
}

class TQConsumer extends Thread {
  private final String name;
  private final TransferQueue<Integer> tQueue;

  public TQConsumer(String name, TransferQueue<Integer> tQueue) {
    this.name = name;
    this.tQueue = tQueue;
  }

  @Override
  public void run() {
    while (true) {
      try {
        Thread.sleep(3000);

        int item = tQueue.take();
        System.out.format("%s removed:  %d%n", name, item);

      }
      catch (InterruptedException e) {
        e.printStackTrace();
      }
    }
  }
}

public class Main {
  public static void main(String[] args) {
    final TransferQueue<Integer> tQueue = new LinkedTransferQueue<>();
    final AtomicInteger sequence = new AtomicInteger();

    for (int i = 0; i < 5; i++) {
      try {
        tQueue.put(sequence.incrementAndGet());
        System.out.println("Initial queue: " + tQueue);

        new TQProducer("Producer-1", tQueue, sequence).start();
        new TQConsumer("Consumer-1", tQueue).start();

      } catch (InterruptedException e) {
        e.printStackTrace();
      }
    }

  }
}

上面的代码生成以下结果。