假设一个线程生产数据,放入仓库中,另一个线程从仓库中取出数据来消费。仓库,可以存储一些数据,容量为maxSize,有两个操作,put()存和take()取。要求,当存数据时,如果仓库已经达到最大存储数量maxSize,则进入等待状态,有人唤醒它时,继续存,每存储一次数据,通知其他线程去取。同理当取数据时,如果仓库中存储数量为0,则进入等待状态,有人唤醒它时,继续取,每取出一次数据,通知其他线程去生产。
封装仓库
class EventStorage {
private int maxSize;
private LinkedList<Object> storage;
public EventStorage() {
maxSize = 10;
storage = new LinkedList<>();
}
/**
* 添加,满了就进入等待状态,等待别人唤醒后再继续添加
* 每添加一次,就通知其他线程去消费
* @param o
*/
public synchronized void put(Object o) {
while (storage.size() == maxSize) {
try {
System.out.println("仓库满了,开始等待。。。");
wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
storage.add(o);
System.out.println("生产了: " + o);
notify();
}
/**
* 取出,为空就进入等待状态,等待别人唤醒后再取
* 每取出一次,就通知其他线程取生产
* @return
*/
public synchronized Object take() {
while (storage.size() == 0) {
try {
System.out.println("仓库空了,开始等待。。。。");
wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
Object o = storage.poll();
System.out.println("消费了:" + o);
notify();
return o;
}
}
生产者和消费者是两个不同的线程,一个负责生产数据,一个负责消费数据,也就是分别对应仓库的put和take操作
生产者
class Producer implements Runnable {
EventStorage storage;
public Producer(EventStorage storage) {
this.storage = storage;
}
@Override
public void run() {
for (int i = 0; i < 1000; i++) {
storage.put(i);
}
}
}
消费者
class Consumer implements Runnable {
EventStorage storage;
public Consumer(EventStorage storage) {
this.storage = storage;
}
@Override
public void run() {
for (int i = 0; i < 1000; i++) {
storage.take();
}
}
}
main方法,测试
public static void main(String[] args) {
EventStorage eventStorage = new EventStorage();
Producer producer = new Producer(eventStorage);
Consumer consumer = new Consumer(eventStorage);
Thread t1 = new Thread(producer);
Thread t2 = new Thread(consumer);
t1.start();
t2.start();
}
打印结果
结果真是太长了,2000多行数据,所以单独放了出来,https://www.jianshu.com/p/ffb8e42fac5f
打印结果中,大多数都是生产10个,再消费10个,不过也有例外的,比如生产6个,消费6个
仓库空了,开始等待。。。。
生产了: 171
生产了: 172
生产了: 173
生产了: 174
生产了: 175
生产了: 176
生产了: 177
消费了:171
消费了:172
消费了:173
消费了:174
消费了:175
消费了:176
消费了:177
是不是以为它只会把内容全部消费完了才能再生产,不是的,比如这几行打印
仓库空了,开始等待。。。。
生产了: 633
生产了: 634
生产了: 635
生产了: 636
消费了:633
消费了:634
消费了:635
生产了: 637
生产了: 638
生产了: 639
生产了: 640
生产了: 641
生产了: 642
生产了: 643
生产了: 644
生产了: 645
仓库满了,开始等待。。。
这次是先生产4个,再消费3个,再生产9个,生产者进入等待状态(wait)。
也就是说,每一次执行notify后都有机会让出锁,让另一个线程执行生产或消费的操作,这完全是由jvm控制的。
待续。。。
网友评论