要实现一个生产者-消费者模式的循环队列,当队列满时等待空闲空间,当队列为空时等待数据,可以使用 Java 的 wait 和 notify 方法来实现线程间的同步和通信。
以下是一个线程安全的、支持等待和通知机制的循环队列实现:
CircularQueue 类
public class CircularQueue<T> {
private T[] queue;
private int front;
private int rear;
private int size;
private int count;
public CircularQueue(int k) {
queue = (T[]) new Object[k];
front = 0;
rear = 0;
size = k;
count = 0;
}
public synchronized void enQueue(T value) throws InterruptedException {
while (isFull()) {
wait();
}
if (isEmpty()) {
notifyAll();
}
queue[rear] = value;
rear = (rear + 1) % size;
count++;
}
public synchronized T deQueue() throws InterruptedException {
while (isEmpty()) {
wait();
}
if (isFull()) {
notifyAll();
}
T value = queue[front];
queue[front] = null;
front = (front + 1) % size;
count--;
return value;
}
public synchronized T Front() {
return isEmpty() ? null : queue[front];
}
public synchronized T Rear() {
return isEmpty() ? null : queue[(rear - 1 + size) % size];
}
public synchronized boolean isEmpty() {
return count == 0;
}
public synchronized boolean isFull() {
return count == size;
}
}
MainActivity 类
在 Android 应用中测试这个线程安全的循环队列,通过不同的线程模拟生产者和消费者。
import android.os.Bundle;
import android.util.Log;
import androidx.appcompat.app.AppCompatActivity;
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
// Initialize a CircularQueue with capacity 5 for String objects
CircularQueue<String> stringQueue = new CircularQueue<>(5);
// Producer thread to enqueue elements
Thread producer = new Thread(() -> {
try {
for (int i = 0; i < 10; i++) {
stringQueue.enQueue("Element " + i);
Log.d("Producer", "Enqueued: Element " + i);
}
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
});
// Consumer thread to dequeue elements
Thread consumer = new Thread(() -> {
try {
for (int i = 0; i < 10; i++) {
String element = stringQueue.deQueue();
Log.d("Consumer", "Dequeued: " + element);
}
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
});
// Start the threads
producer.start();
consumer.start();
// Wait for the threads to finish
try {
producer.join();
consumer.join();
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
Log.d("MainActivity", "Program ended.");
}
}
解释:
CircularQueue Class:
1) 使用泛型 T 来定义循环队列,使其能够存储任何类型的对象。
2) 添加了 count 变量来跟踪当前队列中的元素数量。
3) enQueue 方法:在队列满时等待,有空闲空间后插入元素并唤醒所有等待线程。
4) deQueue 方法:在队列为空时等待,有数据后取出元素并唤醒所有等待线程。
5) Front 和 Rear 方法:获取队列头部和尾部元素。
6) isEmpty 方法:检查队列是否为空。
7) isFull 方法:检查队列是否已满。
MainActivity Class:
1) 初始化一个容量为 5 的 CircularQueue,用于存储 String 对象。
2) 创建生产者线程,不断将元素添加到队列中。
3) 创建消费者线程,不断从队列中取出元素。
4) 两个线程分别调用 enQueue 和 deQueue 方法,并通过日志输出验证方法的正确性。
5) 等待两个线程结束,确保所有操作完成。
这样,通过使用 wait 和 notify 方法,我们就可以实现一个线程安全的、支持等待和通知机制的循环队列。这适用于生产者-消费者模型,在多线程环境下有效地管理资源。