Java ConcurrentLinkedQueue生产消费

在多线程编程中,一个常见的场景是生产者-消费者模型。生产者负责生产数据,消费者负责消费数据。为了实现生产者和消费者之间的安全协作,Java提供了许多并发集合类,其中之一是ConcurrentLinkedQueue

什么是ConcurrentLinkedQueue

ConcurrentLinkedQueue是Java中的一个线程安全的无边界非阻塞队列。它采用链表的数据结构,实现了Queue接口。与其他阻塞队列(如ArrayBlockingQueueLinkedBlockingQueue)不同,ConcurrentLinkedQueue是非阻塞的,不会让线程进入等待状态。

生产者-消费者模型

生产者-消费者模型是一种常见的并发编程模式,用于解决生产者和消费者之间的解耦和协作问题。在该模型中,生产者负责向队列中生产数据,而消费者负责从队列中消费数据。生产者和消费者之间的协作通常通过一个共享的队列实现。

以下是生产者-消费者模型的示意图:

erDiagram
    Producer --|> ConcurrentLinkedQueue
    Consumer --|> ConcurrentLinkedQueue

在Java中,可以使用ConcurrentLinkedQueue作为共享的队列来实现生产者-消费者模型。

使用ConcurrentLinkedQueue实现生产者

以下是一个简单的生产者示例代码:

import java.util.concurrent.ConcurrentLinkedQueue;

public class Producer implements Runnable {
    private ConcurrentLinkedQueue<Integer> queue;

    public Producer(ConcurrentLinkedQueue<Integer> queue) {
        this.queue = queue;
    }

    @Override
    public void run() {
        for (int i = 1; i <= 10; i++) {
            queue.offer(i);
            System.out.println("Produced: " + i);
            try {
                Thread.sleep(100);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
}

在上述代码中,我们创建了一个Producer类,并实现了Runnable接口。在run方法中,我们循环10次,每次生产一个数字,并将其添加到ConcurrentLinkedQueue中。我们还通过Thread.sleep模拟了生产过程的延迟。

使用ConcurrentLinkedQueue实现消费者

以下是一个简单的消费者示例代码:

import java.util.concurrent.ConcurrentLinkedQueue;

public class Consumer implements Runnable {
    private ConcurrentLinkedQueue<Integer> queue;

    public Consumer(ConcurrentLinkedQueue<Integer> queue) {
        this.queue = queue;
    }

    @Override
    public void run() {
        while (true) {
            Integer number = queue.poll();
            if (number == null) {
                break;
            }
            System.out.println("Consumed: " + number);
            try {
                Thread.sleep(200);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
}

在上述代码中,我们创建了一个Consumer类,并实现了Runnable接口。在run方法中,我们使用一个无限循环来不断从ConcurrentLinkedQueue中消费数据。当队列为空时,循环终止。

使用ConcurrentLinkedQueue生产消费

现在我们可以使用上述的生产者和消费者类来实例化线程,并让它们运行。

import java.util.concurrent.ConcurrentLinkedQueue;

public class Main {
    public static void main(String[] args) {
        ConcurrentLinkedQueue<Integer> queue = new ConcurrentLinkedQueue<>();

        Producer producer = new Producer(queue);
        Consumer consumer = new Consumer(queue);

        Thread producerThread = new Thread(producer);
        Thread consumerThread = new Thread(consumer);

        producerThread.start();
        consumerThread.start();
    }
}

在上述代码中,我们创建了一个ConcurrentLinkedQueue实例作为生产者和消费者之间的共享队列。然后,我们创建了一个Producer实例和一个Consumer实例,并将共享队列传递给它们。最后,我们通过Thread类创建了生产者和消费者的线程,并启动线程。

总结

ConcurrentLinkedQueue是Java中一个线程安全的无边界非阻塞队列