一个内存队列,多个生产者线程往内存队列中放数据;多个消费者线程从内存队列中取数据
使用wait()与notify()机制
队列的实现
public class MyQueue {
/**
* 数组队列(总长度为10)
*/
private String[] data = new String[10];
/**
* 出队列的下标
*/
private int getIndex = 0;
/**
* 入队列的下标
*/
private int putIndex = 0;
/**
* 队列已使用的长度
*/
private int size = 0;
/**
* 入队列前尝试获取锁
* @param element
*/
public synchronized void put(String element) {
/**
* 进入方法表示已经获取到了锁
* 判断是否达到了队列的最大长度,如果达到了最大长度则wait,如果没有则进行put0的入队列逻辑,入队列完成后notify唤醒其他线程
*/
if (size == data.length) {
try {
wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
//这里从wait状态被唤醒后需要重新进入put方法判断是否达到队列的最大长度
put(element);
} else {
put0(element);
notify();
}
}
/**
* 入队列
* @param element
*/
private void put0(String element) {
//把当前element放进队列,然后putIndex下标+1
data[putIndex] = element;
++putIndex;
//如果putIndex到达数组尾部,则重新从队列头开始存入
if (putIndex == data.length) {
putIndex = 0;
}
++size;
}
/**
* 出队列前尝试获取锁
* @return
*/
public synchronized String get() {
//判断队列是否已经空了
//如果空了则等待
if (size == 0) {
try {
wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
//被唤醒,然后重新判断是否是空队列
return get();
} else {
//出队列
String result = get0();
//唤醒其他线程
notify();
return result;
}
}
/**
* 出队列
* @return
*/
private String get0() {
//依次从getIndex向后取,这次取getIndex的,下次进入get0方法就取getIndex+1的
String result = data[getIndex];
++getIndex;
//如果getIndex到达数组的最大值,则从队列头开始取
if (getIndex == data.length) {
getIndex = 0;
}
--size;
return result;
}
}
生产者
/**
* 生产者
*/
public class ProducerThread extends Thread {
private final MyQueue myQueue;
private final Random random = new Random();
private int index = 0;
public ProducerThread(MyQueue myQueue) {
this.myQueue = myQueue;
}
@Override
public void run() {
//不停的生产
while (true) {
String tmp = "ele-"+Thread.currentThread().getName()+"-" + index;
//put方法有synchronize,锁的是myQueue自己
myQueue.put(tmp);
System.out.println("添加元素:" + tmp);
index++;
try {
Thread.sleep(random.nextInt(1000));
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
消费者
/**
* 消费者
*/
public class ConsumerThread extends Thread {
private final MyQueue myQueue;
private final Random random = new Random();
public ConsumerThread(MyQueue myQueue) {
this.myQueue = myQueue;
}
@Override
public void run() {
while (true) {
//get方法有synchronize,锁的是myQueue自己
String s = myQueue.get();
System.out.println("\t\t消费元素:" + s);
try {
Thread.sleep(random.nextInt(1000));
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
测试代码
public class Main {
public static void main(String[] args) {
MyQueue myQueue = new MyQueue();
for (int i = 0; i < 3; i++) {
//消费者消费同一个队列
new ConsumerThread(myQueue).start();
}
for (int i = 0; i < 5; i++) {
//生产者放入同一个队列
new ProducerThread(myQueue).start();
}
}
}