原创

java面试题-BlockingQueue的实现类


介绍

在Java多线程编程中,阻塞队列(BlockingQueue)是一种强大的工具,用于实现线程之间的安全数据传递。本教程将深入研究阻塞队列的概念和常见实现类,为初学者提供详细的示例代码和清晰的解释。

阻塞队列基础操作

1. 抛出异常的操作方法

add(e)

ArrayBlockingQueue 是一个有边界的阻塞队列,通过数组实现。在初始化时需要指定容量,且容量不可更改。

BlockingQueue<String> arrayBlockingQueue = new ArrayBlockingQueue<>(3);arrayBlockingQueue.add("Item1");arrayBlockingQueue.add("Item2");arrayBlockingQueue.add("Item3");// arrayBlockingQueue.add("Item4");  // 抛出异常,队列已满

remove()

remove() 用于移除队头元素,若队列为空则抛出异常。

try {    String item = arrayBlockingQueue.remove();    System.out.println("Removed item: " + item);} catch (NoSuchElementException e) {    System.out.println("Queue is empty");}

element()

element() 返回队头元素但不移除,若队列为空则抛出异常。

try {    String item = arrayBlockingQueue.element();    System.out.println("Front item: " + item);} catch (NoSuchElementException e) {    System.out.println("Queue is empty");}

2. 返回特殊值的操作方法

offer(e)

LinkedBlockingQueue 是一个由链表结构组成的无界阻塞队列,可以不断地添加元素。

boolean success = linkedBlockingQueue.offer("Item1");System.out.println("Offer success: " + success);

poll()

poll() 移除并返回队头元素,若队列为空则返回 null

String item = linkedBlockingQueue.poll();if (item != null) {    System.out.println("Removed item: " + item);} else {    System.out.println("Queue is empty");}

peek()

peek() 返回队头元素但不移除,若队列为空则返回 null

String item = linkedBlockingQueue.peek();if (item != null) {    System.out.println("Front item: " + item);} else {    System.out.println("Queue is empty");}

3. 阻塞的操作方法

put(e)

put() 将元素添加到队列,若队列已满则阻塞等待。

linkedBlockingQueue.put("Item1");System.out.println("Item1 added to the queue");

take()

take() 移除并返回队头元素,若队列为空则阻塞等待。

String item = linkedBlockingQueue.take();System.out.println("Removed item: " + item);

JDK 6中的阻塞队列实现类

在Java 6中,有几个主要的阻塞队列实现类,每个都有其特定的用途。

1. ArrayBlockingQueue

ArrayBlockingQueue 是一个有边界的阻塞队列,内部使用数组实现。它按照先进先出(FIFO)的原则排序元素。

BlockingQueue<String> arrayBlockingQueue = new ArrayBlockingQueue<>(3);

2. DelayQueue

DelayQueue 是一个使用优先级队列实现的无界阻塞队列,其中的元素必须实现 java.util.concurrent.Delayed 接口。

BlockingQueue<DelayedElement> delayQueue = new DelayQueue<>();

3. LinkedBlockingQueue

LinkedBlockingQueue 是一个由链表结构组成的无界阻塞队列。可以选择指定容量,不指定则为无限容量。

BlockingQueue<String> linkedBlockingQueue = new LinkedBlockingQueue<>();

4. PriorityBlockingQueue

PriorityBlockingQueue 是一个支持优先级排序的无界阻塞队列。元素需要实现 java.lang.Comparable 接口。

BlockingQueue<Integer> priorityBlockingQueue = new PriorityBlockingQueue<>();

5. SynchronousQueue

SynchronousQueue 是一个不存储元素的阻塞队列。每个插入操作必须等待另一个线程的相应移除操作。

BlockingQueue<String> synchronousQueue = new SynchronousQueue<>();

示例代码与应用场景

1. DelayQueue的应用

场景1:定时关闭连接

public class DelayedElement implements Delayed {    private long expired;    private long delay;
DelayedElement(long delay) { this.delay = delay; this.expired = (delay + System.currentTimeMillis()); }
@Override public long getDelay(TimeUnit unit) { return (expired - System.currentTimeMillis()); }
@Override public int compareTo(Delayed o) { DelayedElement cached = (DelayedElement) o; return cached.getExpired() > expired ? 1 : -1; }
public long getExpired() { return expired; }}
public class DelayQueueExample { public static void main(String[] args) throws InterruptedException { DelayQueue<DelayedElement> queue = new DelayQueue<>(); DelayedElement ele = new DelayedElement(3000); queue.put(ele); System.out.println(queue.take()); }}

场景2:学生考试

public class Student implements Runnable, Delayed {    private String name;    private long costTime;    private long finishedTime;
public Student(String name, long costTime) { this.name = name; this.costTime = costTime; this.finishedTime = costTime + System.currentTimeMillis(); }
@Override public void run() { System.out.println(name + " submitted the exam in " + costTime / 1000 + " seconds"); }
@Override public long getDelay(TimeUnit unit) { return (finishedTime - System.currentTimeMillis()); }
@Override public int compareTo(Delayed o) { Student other
= (Student) o; return costTime >= other.costTime ? 1 : -1; }}
public class Teacher { static final int STUDENT_SIZE = 30;
public static void main(String[] args) throws InterruptedException { Random r = new Random(); DelayQueue<Student> students = new DelayQueue<>(); ExecutorService exec = Executors.newFixedThreadPool(STUDENT_SIZE);
for (int i = 0; i < STUDENT_SIZE; i++) { students.put(new Student("Student " + (i + 1), 3000 + r.nextInt(10000))); }
while (!students.isEmpty()) { exec.execute(students.take()); }
exec.shutdown(); }}

2. PriorityBlockingQueue的应用

场景:按优先级排序

public class PriorityElement implements Comparable<PriorityElement> {    private int priority;
PriorityElement(int priority) { this.priority = priority; }
@Override public int compareTo(PriorityElement o) { return Integer.compare(priority, o.getPriority()); }
public int getPriority() { return priority; }
@Override public String toString() { return "PriorityElement [priority=" + priority + "]"; }}
public class PriorityBlockingQueueExample { public static void main(String[] args) throws InterruptedException { PriorityBlockingQueue<PriorityElement> queue = new PriorityBlockingQueue<>();
for (int i = 0; i < 5; i++) { Random random = new Random(); PriorityElement ele = new PriorityElement(random.nextInt(10)); queue.put(ele); }
while (!queue.isEmpty()) { System.out.println(queue.take()); } }}

结语

通过本教程,我们深入研究了Java阻塞队列及其实现类。通过清晰的示例代码和详细的解释,读者可以更好地理解阻塞队列在多线程编程中的应用。选择合适的阻塞队列实现类对于不同的场景和需求至关重要。关注站长获取更多详情。


正文到此结束
本文目录