背景
多线程中的生产者和消费者我们经常会使用到,而嫁接生产者和消费者之前的桥梁可以是队列也可以是栈,我们今天就使用循环队列来手写一个同步循环队列demo
循环队列特点:FIFO(先进先出)
示例demo
同步循环队列:
/**
* 同步队列
**/
public class SynchronizedQueue<T> {
private static final int DEFAULT_SIZE = 128;
private int size;
private int insert = 0;
private int remove = 0;
private Object[] queue;
public SynchronizedQueue() {
this(DEFAULT_SIZE);
}
public SynchronizedQueue(int size) {
this.size = size;
queue = new Object[size];
}
public synchronized boolean offer(T object) {
queue[insert++] = object;
// 插满数据后,重置指针到初始值继续往队列中添加数据
if (insert == size) {
insert = 0;
}
if (insert == remove) {
// 当insert指针和remove指针到达同一个地方时,说明队列满了,此时需要拓展队列内存
expand();
}
return true;
}
public synchronized T poll() {
if (insert == remove) {
return null;
}
T result = (T) queue[remove];
queue[remove] = null;
remove++;
// 当remove指针到达size时,需要重置到初始值0,以便重新移除queue对象
if (remove == size) {
remove = 0;
}
return result;
}
public synchronized int size() {
int result = insert - remove;
if (result < 0) {
result += size;
}
return result;
}
public synchronized void clear() {
// 这种方式是重新定义一个新数组
// queue = new Object[size];
//还有一种方式是,清空queue中对象
for (int i = 0; i < size(); i++) {
queue[i] = null;
}
insert = 0;
remove = 0;
}
private void expand() {
System.out.println("expand is run ,size:" + size);
int newSize = size * 2;
Object[] newQueue = new Object[newSize];
System.arraycopy(queue, insert, newQueue, 0, size - insert);
System.arraycopy(queue, 0, newQueue, size - insert, insert);
insert = size;
remove = 0;
queue = newQueue;
size = newSize;
}
}
生产者和消费者测试类:
/**
* 队列测试类
**/
public class QueueTest {
public static void main(String[] args) {
SynchronizedQueue<String> synchronizedQueue = new SynchronizedQueue<>(5);
// 生产者
new Thread(() -> {
int index = 0;
for (; ; ) {
index++;
synchronizedQueue.offer("producer" + index);
if (index % 3 == 0) {
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
if (index >= 10) {
return;
}
}
}).start();
// 消费者
new Thread(() -> {
for (; ; ) {
if (synchronizedQueue.size() > 0) {
System.out.println("时间:" + new Date() +", 消费者消费:" + synchronizedQueue.poll());
}
}
}).start();
}
}
运行结果: