生产者和消费者彼此之间不直接沟通,而通过阻塞队列来进行通讯,当生产者生产的商品不足时,生产者开始生产,消费者进行阻塞,当生产者生产充足的商品后,唤醒消费者,进行出售......所以生产者生产完数据之后不会等待消费者处理,直接唤醒阻塞队列中的所有线程,同时自身阻塞,消费者在消费完成后,同时唤醒阻塞队列中的所有线程,自身进行阻塞.......阻塞队列就相当于一个缓冲区,平衡了生产者和消费者的能力
注意:每个锁对象有两个队列,一个是就绪队列,一个是阻塞队列,就绪队列存储了将要获得锁的线程,阻塞队列存储了被阻塞的线程,一个线程被唤醒后,才会进入就绪队列,等待CPU的调度,一个线程被wait后,就会进入阻塞队列,等待下一次被唤醒,得到notify通知后只是从等待队列移出来。在移出来的时候,有可能不直接进入就绪队列直接拿到对象锁,但大多情况下是直接进入就绪队列
商品类
package com.lin;
import org.omg.PortableServer.THREAD_POLICY_ID;
/**
* Description:
* Author: llf
* Created in 2019/8/5 14:06
*/
public class Goods {
private String goodsName;
private int count;
public Goods() {
}
public synchronized void set(String goodsName) throws InterruptedException {
//当生产者生产产品数量超过5个,则等待阻塞,释放对象锁,由消费者竞争锁
if (this.count>5) {
System.out.println("还有商品库存,等待消费者消费");
wait();
}
this.goodsName=goodsName;
this.count++;
Thread.sleep(1000);
System.out.println("生产"+toString());
//唤醒消费者线程,此时已有商品
notify();
}
public synchronized void get() throws InterruptedException {
当没有商品买了,自身阻塞等待,释放对象锁,等待生产者生产出商品在竞争锁继续运行
if (this.count==0) {
System.out.println("商品已卖完,等待生产者生产");
wait();
}
this.count=this.count-1;
Thread.sleep(1000);
System.out.println("消费"+toString());
//唤醒生产者线程,此时可能会即将没有商品
notify();
}
@Override
public String toString() {
return "Goods{" +
"goodsName='" + goodsName + '\'' +
", count=" + count +
'}';
}
}
生产者
package com.lin;
/**
* Description:
* Author: llf
* Created in 2019/8/5 14:11
*/
public class Producer implements Runnable{
private Goods goods;
public Producer(Goods goods) {
super();
this.goods = goods;
}
@Override
public void run() {
try {
this.goods.set("小黑瓶");
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
消费者
package com.lin;
/**
* Description:
* Author: llf
* Created in 2019/8/5 14:11
*/
public class Consumer implements Runnable{
private Goods goods;
public Consumer(Goods goods) {
this.goods = goods;
}
@Override
public void run() {
try {
this.goods.get();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
测试
package com.lin;
import java.util.ArrayList;
import java.util.List;
/**
* Description:
* Author: llf
* Created in 2019/8/5 14:17
*/
public class Main {
public static void main(String[] args) throws InterruptedException {
Goods goods=new Goods();
Thread thread1=new Thread(new Producer(goods),"生产者");
Thread thread2=new Thread(new Consumer(goods),"消费者");
thread1.start();
thread2.start();
}
}
程序运行结果
生产者生产Goods{goodsName='小黑瓶', count=1}
生产者生产Goods{goodsName='小黑瓶', count=2}
生产者生产Goods{goodsName='小黑瓶', count=3}
生产者生产Goods{goodsName='小黑瓶', count=4}
生产者生产Goods{goodsName='小黑瓶', count=5}
生产者生产Goods{goodsName='小黑瓶', count=6}
消费者消费Goods{goodsName='小黑瓶', count=5}
生产者生产Goods{goodsName='小黑瓶', count=6}
还有商品库存,等待消费者消费
消费者消费Goods{goodsName='小黑瓶', count=5}
消费者消费Goods{goodsName='小黑瓶', count=4}
消费者消费Goods{goodsName='小黑瓶', count=3}
消费者消费Goods{goodsName='小黑瓶', count=2}
生产者生产Goods{goodsName='小黑瓶', count=3}
消费者消费Goods{goodsName='小黑瓶', count=2}
消费者消费Goods{goodsName='小黑瓶', count=1}
消费者消费Goods{goodsName='小黑瓶', count=0}
商品已卖完,等待生产者生产
商品类
package com.lin;
/**
* Description:
* Author: llf
* Created in 2019/8/5 14:06
*/
public class Goods {
private String goodsName;
private int count;
public Goods() {
}
public synchronized void set(String goodsName) throws InterruptedException {
//若此时商品已充足,不需生产,则循环阻塞所有生产者线程
while (this.count>5) {
System.out.println("还有商品库存,等待消费者消费");
wait();
}
this.goodsName=goodsName;
this.count++;
Thread.sleep(1000);
System.out.print(Thread.currentThread().getName());
System.out.println("生产"+toString());
//已生产商品,唤醒所有线程
notifyAll();
}
public synchronized void get() throws InterruptedException {
//已无商品可买,需要生产者生产,循环阻塞消费者线程
while (this.count==0) {
System.out.println("商品已卖完,等待生产者生产");
wait();
}
this.count=this.count-1;
Thread.sleep(1000);
System.out.print(Thread.currentThread().getName());
System.out.println("消费"+toString());
//可能商品数量不足,唤醒所有线程
notifyAll();
}
@Override
public String toString() {
return "Goods{" +
"goodsName='" + goodsName + '\'' +
", count=" + count +
'}';
}
}
生产者
package com.lin;
/**
* Description:
* Author: llf
* Created in 2019/8/5 14:11
*/
public class Producer implements Runnable{
private Goods goods;
public Producer(Goods goods) {
super();
this.goods = goods;
}
@Override
public void run() {
while(true) {
try {
this.goods.set("小黑瓶");
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
消费者
package com.lin;
/**
* Description:
* Author: llf
* Created in 2019/8/5 14:11
*/
public class Consumer implements Runnable{
private Goods goods;
public Consumer(Goods goods) {
this.goods = goods;
}
@Override
public void run() {
while (true) {
try {
this.goods.get();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
测试类
package com.lin;
import java.util.ArrayList;
import java.util.List;
/**
* Description:
* Author: llf
* Created in 2019/8/5 14:17
*/
public class Main {
public static void main(String[] args) throws InterruptedException {
Goods goods=new Goods();
List threadList=new ArrayList();
for (int i = 0; i <10 ; i++) {
Thread thread1=new Thread(new Producer(goods),"生产者"+i);
threadList.add(thread1);
}
for (int i = 0; i < 6; i++) {
Thread thread2=new Thread(new Consumer(goods),"消费者"+i);
threadList.add(thread2);
}
for (Thread thread:threadList) {
thread.start();
}
}
}
运行结果
生产者0生产Goods{goodsName='小黑瓶', count=1}
生产者0生产Goods{goodsName='小黑瓶', count=2}
生产者0生产Goods{goodsName='小黑瓶', count=3}
生产者0生产Goods{goodsName='小黑瓶', count=4}
生产者0生产Goods{goodsName='小黑瓶', count=5}
生产者0生产Goods{goodsName='小黑瓶', count=6}
消费者5消费Goods{goodsName='小黑瓶', count=5}
消费者3消费Goods{goodsName='小黑瓶', count=4}
消费者3消费Goods{goodsName='小黑瓶', count=3}
消费者3消费Goods{goodsName='小黑瓶', count=2}
消费者3消费Goods{goodsName='小黑瓶', count=1}
消费者4消费Goods{goodsName='小黑瓶', count=0}
商品已卖完,等待生产者生产
商品已卖完,等待生产者生产
商品已卖完,等待生产者生产
商品已卖完,等待生产者生产
生产者9生产Goods{goodsName='小黑瓶', count=1}