java实现一个简单的消息队列

663 阅读1分钟

Java中可以通过设计一个简单的生产者消费者模型来自己实现消息队列。具体实现可以使用Java多线程编程中的管程(Monitor)来进行实现。

步骤如下:

1.定义一个存储消息的数据结构,例如数组或者链表等。 2.定义一个锁,并在锁上实现一个条件变量(Condition),用于阻塞和唤醒生产者和消费者线程。 3.定义一个生产者类(Producer)和一个消费者类(Consumer),分别用于生产和消费消息。这两个类都需要实现Runnable接口,并且在run方法中进行消息的生产或者消费。 4.在生产者和消费者类中,分别用while循环来不断进行生产和消费操作,当队列满了或者为空时,使用条件变量进行阻塞。 5.在消息队列类中,提供加入消息和获取消息的方法,这两个方法需要进行同步,并且在加入和获取消息时需要对条件变量进行signal操作以唤醒阻塞的线程。 6.在主函数中启动生产者和消费者线程,使得消息队列可以开始运行并进行消息的生产与消费。

import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

public class MessageQueue {
    private static final int CAPACITY = 10;
    private String[] messageQueue = new String[CAPACITY];
    private int head = 0;
    private int tail = 0;

    private final Lock lock = new ReentrantLock();
    private final Condition notFull = lock.newCondition();
    private final Condition notEmpty = lock.newCondition();

    public void put(String message) throws InterruptedException {
        lock.lock();
        try {
            while ((tail + 1) % CAPACITY == head) {
                notFull.await();
            }
            messageQueue[tail] = message;
            tail = (tail + 1) % CAPACITY;
            notEmpty.signal();
        } finally {
            lock.unlock();
        }
    }

    public String take() throws InterruptedException {
        lock.lock();
        try {
            while (head == tail) {
                notEmpty.await();
            }
            String message = messageQueue[head];
            head = (head + 1) % CAPACITY;
            notFull.signal();
            return message;
        } finally {
            lock.unlock();
        }
    }

    public static void main(String[] args) {
        MessageQueue messageQueue = new MessageQueue();
        Thread producer = new Thread(() -> {
            for (int i = 0; i < 20; i++) {
                String message = "message " + i;
                try {
                    messageQueue.put(message);
                    System.out.println("Produced message: " + message);
                    Thread.sleep(100);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        });

        Thread consumer = new Thread(() -> {
            for (int i = 0; i < 20; i++) {
                try {
                    String message = messageQueue.take();
                    System.out.println("Consumed message: " + message);
                    Thread.sleep(300);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        });

        producer.start();
        consumer.start();
    }
}