一、生产者消费者模型
该模型是通过一个容器来解决生产者和消费者的强耦合问题。生产者和消费者彼此之间不直接通讯,而通过阻塞队列来进行通讯,所以生产者生产完数据之后不用等待消费者处理,直接扔给阻塞队列,消费者不找生产者要数据,而是直接从阻塞队列里取,阻塞队列就相当于一个缓冲区,平衡了生产者和消费者的处理能力。
二、单线程之生产者与消费者
单线程模式:生产者生产商品时,消费者不能消费商品;反之,消费者消费商品时,生产者不能生产商品,即进程在执行时一次只能有线程。
这里我们设置缓冲区的容量为1(缓冲区中存放数据)。
1.商品类
商品类中定义了生产商品和消费商品的方法
(生产、消费商品是商品的属性行为,所以我们定义在商品类中,同时这样也可以直接对商品的成员变量进行操作)
package SingleProducerConsumer;
/*单线程模式:生产者生产商品时,消费者不能消费商品,反之亦然
所以货架上最多有一个商品
* */
public class Goods {
private String goodsName;
private int count;//count为线程执行对应操作前的库存量
@Override
public String toString() {
return "Goods{" +
"goodsName='" + goodsName + '\'' +
", count=" + count +
'}';
}
//生产商品
public synchronized void set(String goodsName) {
//先进行判断,再执行相应操作
if(count>0){
System.out.println("商品还有库存,等会再生产!");
try {
//某些条件没有被满足,调用wait方法暂停自己的执行
this.wait();//暂停生产者的执行,等待消费者消费
} catch (InterruptedException e) {
e.printStackTrace();
}
}
this.goodsName=goodsName;
System.out.println(Thread.currentThread().getName()+"生产"+toString());
count++;
notify();
}
//消费商品
public synchronized void get() {
//先进行判断,再执行相应操作
if(count<0){
System.out.println("商品没有库存,等会再消费!");
try {
this.wait();//暂停生产者的执行,等待消费者消费
} catch (InterruptedException e) {
e.printStackTrace();
}
}
System.out.println(Thread.currentThread().getName()+"消费"+toString());
count--;
notify();//唤醒生产者继续生产线程
}
}
2.生产者类
package SingleProducerConsumer;
public class Producer implements Runnable {
private Goods goods;
public Producer(Goods goods) {
this.goods = goods;
}
//生产者生产商品
public void run() {
goods.set("蛋黄酥");
}
}
3.消费者类
package SingleProducerConsumer;
public class Consumer implements Runnable{
Goods goods;
public Consumer(Goods goods) {
this.goods = goods;
}
//消费者消费商品
public void run() {
goods.get();
}
}
4.测试类
package SingleProducerConsumer;
public class Test {
public static void main(String[] args) throws InterruptedException {
//传递一个商品,注意:生产者和消费者必须对同一个商品进行处理
Goods goods = new Goods();
Producer producer = new Producer(goods);
Consumer consumer = new Consumer(goods);
Thread producerThread= new Thread(producer, "生产者线程");
Thread consumerThread= new Thread(consumer, "消费者线程");
producerThread.start();
//当前主线程休眠1秒
Thread.sleep(1000);
consumerThread.start();
}
}
5.注意事项
1.生产者线程和消费者线程必须对同一个商品类进行处理,所以在类Producer,Consumer中传入商品类时,不能写成Goods goods=new Goods()
2.wait方法需要被try-catch包含
3.wait/notify/notifyAll都必须包裹在同步代码块/同步方法中
4.同步代码块/同步方法的最后不要掉了notify/notifyAll方法
三、个人感悟
果然实践是检验真理的唯一标准,这个单线程的模型我以为我懂了,结果敲代码时各种错误以及发现了很多需要注意的点,所以还是要动手!!!
四、多线程之生产者与消费者
这里先挖一个坑,以后再填