生产者生产商品,消费者进行消费在这个过程中有一个强耦合问题,消费者有需求时可能生产者并没有生产;为了解决这个问题在生产者和消费者之间加入一个阻塞队列,先通知生产者生产一定库存,然后进入等待当消费者消费完后消费者等待生产者再次工作;
在多线程中要达到这个目的就要借助wait()和notify()这两个属于Object类的方法,线程中的sleep()和wait()有着很大区别;
sleep()是Thread类中定义的方法,到了一定的时间后该线程自动唤醒,不会释放对象锁。
wait()是Object类中定义的方法,要想唤醒必须使用notify()、notifyAll()方法才能唤醒,会释放对象锁;
下面就是生产者消费者模型代码
class Goods {
private final String name;
Goods(String name) {
this.name = name;
}
@Override
public String toString() {
return "Goods{" +
"name='" + name + '\'' +
'}';
}
}
class Producer implements Runnable {
private final Queue<Goods> goods;
private final Object monitor;
private final AtomicInteger atomicInteger;
Producer(Queue<Goods> goods, Object monitor, AtomicInteger atomicInteger) {
this.goods = goods;
this.monitor = monitor;
this.atomicInteger = atomicInteger;
}
@Override
public void run() {
while (true) {
try {
Thread.sleep(500);
} catch (InterruptedException e) {
e.printStackTrace();
}
synchronized (monitor) {
if (this.goods.size() >= 10) {
try {
this.monitor.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
} else {
Goods good = new Goods("商品" + atomicInteger.getAndAdd(1));
goods.add(good);
System.out.println("生产者生产商品:" + good);
}
}
}
}
}
class Customer implements Runnable {
private final Queue<Goods> goods;
private final Object monitor;
Customer(Queue<Goods> goods, Object monitor) {
this.goods = goods;
this.monitor = monitor;
}
@Override
public void run() {
while (true) {
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
synchronized (monitor) {
if (goods.isEmpty()) {
this.monitor.notify();
} else {
Goods g = goods.poll();
System.out.println("消费者消费: " + g);
}
}
}
}
}
在Producer类中用到了一个叫做AtomicInteger的类,如果同一个数据不做处理被多线程同时访问肯定会发生错误,此时就有两种方法可以避免一个是利用同步块,另一个就是运用这个类进行线程安全的加减操作;
测试类:
public class ProductToCustomer {
public static void main(String[] args) {
Queue<Goods> n = new LinkedList<>();
Object o = new Object();
Producer producer = new Producer(n, o, new AtomicInteger(1));
Customer customer = new Customer(n, o);
Thread start = new Thread(producer, "生产者");
Thread end = new Thread(customer, "消费者");
end.start();
start.start();
}
}