示例代码
import java.util.Date;
import java.util.LinkedList;
public class Deque {
//最大容量
private volatile int maxSize;
//链表集合
private LinkedList<Integer> datas;
public Deque(int maxSize, LinkedList<Integer> datas) {
this.maxSize = maxSize;
this.datas = datas;
}
public synchronized void put(Integer integer) throws InterruptedException {
//如果队列已经满了,就不要再放数据进去了,等待消费者消费
while (maxSize == datas.size()) {
wait();
}
datas.add(integer);
System.out.println("在" + new Date() + "时,生产者生产了第" + integer + "个商品");
notify();
}
public synchronized Integer poll() throws InterruptedException {
//如果队列已经空了,等待生产者生产数据
while (0 == datas.size()) {
wait();
}
Integer integer = datas.poll();
System.out.println("在" + new Date() + "时,消费者消费了第" + integer + "个商品");
notify();
return integer;
}
//生产者类
static class Producer implements Runnable {
private Deque deque;
public Producer(Deque deque) {
this.deque = deque;
}
@Override
public void run() {
for (int i = 1; i <= 100; i++) {
try {
deque.put(i);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
//消费者类
static class Consumer implements Runnable {
private Deque deque;
public Consumer(Deque deque) {
this.deque = deque;
}
@Override
public void run() {
for (int i = 1; i <= 100; i++) {
try {
deque.poll();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
public static void main(String[] args) throws InterruptedException {
Deque deque = new Deque(10, new LinkedList<>());
Producer producer = new Producer(deque);
Consumer consumer = new Consumer(deque);
new Thread(producer).start();
new Thread(consumer).start();
}
}
运行部分结果如下:
可以发现生产者和消费者交替运行,并不用等到队列满了才做消费,有可能生产了2个,就马上消费了2个,生产了9个,就马上消费9个。
而这里面用wait()和notify()是为了做到当队列满时或者空了时,生产者或者消费者进入了等待状态,可以被另一个线程唤醒继续工作。
总结
这里用wait()和notify()的作用,可以简单的理解成,当队列满时,生产者进入等待状态,这时消费者消费了一个商品,队列不满了,可以再生产数据了,所以立马唤醒生产者,让生产者准备生产数据,当然,唤醒了不代表就能够成功抢到资源来运行,完全有可能消费了好几轮,生产者才抢到资源运行。同理的,当队列为空时,消费者没商品可以消费了,就进入了等待状态,这时生产者生产了一个商品,队列里有了数据可以消费了,所以就唤醒消费者让它准备消费。