题目如下:
使用 wait notify 实现一个队列,队列有2个方法,add 和 get 。add方法往队列中添加元素,get方法往队列中获得元素。队列必须是线程安全的。如果get执行时,队列为空,线程必须阻塞等待,直到有队列有数据。如果add时,队列已经满,则add线程要等待,直到队列有空闲空间。
实现这么一个队列,并写一个测试代码,使他工作在多线程的环境下,证明,它的工作是正确的。给出程序和运行的截图。
问题分析:依据以上题目要求,多线程操作时将队列锁定即可。本人使用了两种方式去模拟一个队列,一种是数组另一种是链表形式的队列。
测试代码如下:
// static ArrayQueue _queue = new ArrayQueue();
static LinkedQueue<Object> _queue = new LinkedQueue<>();
static int maxAccess = 10;
@Test
public void test02() throws Exception {
// 使用 wait notify 实现一个队列,队列有2个方法,add 和 get
// 。add方法往队列中添加元素,get方法往队列中获得元素。队列必须是线程安全的。
// 如果get执行时,队列为空,线程必须阻塞等待,直到有队列有数据。如果add时,队列已经满,
// 则add线程要等待,直到队列有空闲空间。
// 实现这么一个队列,并写一个测试代码,使他工作在多线程的环境下,证明,它的工作是正确的。给出程序和运行的截图。
Thread a1 = new Thread(new addThread(), "AddThread-1");
Thread a2 = new Thread(new addThread(), "AddThread-2");
Thread a3 = new Thread(new addThread(), "AddThread-3");
a1.start();
a2.start();
a3.start();
Thread g1 = new Thread(new getThread(), "GetThread-1");
Thread g2 = new Thread(new getThread(), "GetThread-2");
Thread g3 = new Thread(new getThread(), "GetThread-3");
g1.start();
g2.start();
g3.start();
a1.join();
a2.join();
a3.join();
g1.join();
g2.join();
g3.join();
}
/**
* 链表队列
* @author sunhf
*
*/
static class LinkedQueue<T> {
private Node<T> head; //头节点
private Node<T> tail; //尾节点
public void add(T obj) {
if(head == null) {
head = new Node<T>(obj, tail);
tail = head;
} else {
Node<T> next = new Node<T>(obj, null);
tail.setNext(next);
tail = next;
}
}
public Object poll() {
T result = head.getContent();
head = head.getNext();
return result;
}
public int size() {
int length = 0;
Node<T> temp = head;
while(true) {
if(temp == null) {
return length;
} else {
temp = temp.getNext();
length++;
}
}
}
class Node<T> {
private T content;
private Node<T> next; //下一个节点
public Node(T content, Node<T> next) {
super();
this.content = content;
this.next = next;
}
public T getContent() {
return content;
}
public void setContent(T content) {
this.content = content;
}
public Node<T> getNext() {
return next;
}
public void setNext(Node<T> next) {
this.next = next;
}
}
}
/**
* 数组队列
* @author sunhf
*
*/
static class ArrayQueue {
private Object[] _queue = new Object[10];
private int index = 0;
public void add(Object obj) {
if(index == _queue.length) {
Object[] temp = new Object[_queue.length];
System.arraycopy(_queue, 0, temp, 0, _queue.length * 2); // 队列扩容
_queue = temp;
}
_queue[index] = obj;
index++;
}
public Object poll() {
Object rs = _queue[0]; // 消费队列中第一个元素
Object[] temp = new Object[_queue.length];
System.arraycopy(_queue, 1, temp, 0, _queue.length - 1); // 向前移动队列
_queue = temp;
index--;
return rs;
}
public int size() {
for(int i = 0; i < _queue.length; i++) {
if(_queue[i] == null) {
return i;
}
}
return _queue.length;
}
}
class addThread implements Runnable {
@Override
public void run() {
while (true) {
synchronized (_queue) {
System.out.println("生产者->" + _queue.size());
if (_queue.size() == maxAccess) {
try {
System.out.println("消费队列已满,等待消费……");
_queue.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
} else {
_queue.add(_queue.size() + 1);
_queue.notify();
}
}
}
}
}
class getThread implements Runnable {
@Override
public void run() {
while (true) {
synchronized (_queue) {
if (_queue.size() == 0) {
try {
System.out.println("消费队列为空,等待生产……");
_queue.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
} else {
System.out.println("消费者->" + _queue.poll());
_queue.notify();
}
}
}
}
}