生产者消费者问题(使用notify和wait设计)
设计:产品-product类;
产品库:productRepository类
生产者线程
消费者线程
product.java
public class Product{
private String name;
private long productNo;
public Product(String name,long productNo){
this.name = name;
this.productNo = productNo;
}
public String getName(){
return name;
}
public void setName(){
this.name = name;
}
public long getProductNo(){
return productNo;
}
public void setProductNo(){
this.productNo = productNo;
}
@重写
public String toString(){
return "Product{"+"name'="+name+'\"+",productNo["+productNo+'}';
}
}
ProductRepository.java
public class ProductRepository(){
private Vector<Product> products = new Vector<>();
private static final int MAX_NUM = 10;
public void produce(){
synchronized(products){
if(products.size()==MAX_NUM){
try{
wait();
}catch(InterruptedException e){
e.printStackTrace();
}
}
//products.size()<MAX_NUM 如果仓库还没有满
Product product = new Product("包子",System.currentTimeMillis());
products.add(product);
try{
Thread.sleep(1000);
}catch(InterruptedException e){
e.printStackTrace();
}
System.out.println(Thread.currrentThread().getName()+"生产了: "+product+" ,产品仓库当前数量: "+ products.size());
//通知等待的消费者来消费
notify();
}
}
public void consume(){
synchronized(products){
if(products.size()===0){
try{
wait();
}catch(InterruptedException e){
e.printStackTrace();
}
}
Product product = products.firstElement();
products.remove(0);
System.out.println(Thread.currentThread().getName()+"消费了: "+ product+" ,产品仓库当前数量: "+ products.size());
try{
Thread.sleep(2000);
}catch(InterruptedException){
e.printStackTrace();
}
//通知生产者生产
notify();
}
}
}
consumer.java
public class Consumer implements Runnable{
private ProductRepository repository;
public Consumer(ProductRepository repository){
this.repository = repository;
}
@Override
public void run(){
while(true){
repository.consume();
}
}
}
Producer.java
public class Producer implments Runnable{
private ProductRepository repository;
public Producer(ProductRepository repository){
this.repository = repository;
}
@Override
public void run(){
while(true){
repository.produce();
}
}
}
测试类
public class ProductorConsumerTest {
/**
* 一个生产者,一个消费者
* @throws InterruptedException
*/
public static void oneProducerAndOneConsumer() throws InterruptedException {
ProductRepository repository = new ProductRepository();
Consumer consumer = new Consumer(repository);
Producer producer = new Producer(repository);
Thread t1 = new Thread(producer,"producer-A");
Thread t2 = new Thread(consumer,"consumer-B");
t1.start();
t2.start();
t1.join();
t2.join(); //join(): 主线程等待t1线程和禾t2线程都执行完
}
public static void main(String[] args) throws InterruptedException {
oneProducerAndOneConsumer();
}
}
结果:
Exception in thread "producer-A" java.lang.IllegalMonitorStateException
at java.lang.Object.notify(Native Method)
at com.gml.pinlor.thread.pcproblem.ProductRepository.produce(ProductRepository.java:33)
at com.gml.pinlor.thread.pcproblem.Producer.run(Producer.java:17)
at java.lang.Thread.run(Thread.java:745)
producer-A 生产了: Product{name='包子', productNo=1521786358450} ,产品仓库当前数量: 1
consumer-B 消费了: Product{name='包子', productNo=1521786358450} ,产品仓库当前数量: 0
java.lang.IllegalMonitorStateException
是什么鬼?在API中是这么描述的:
Thrown to indicate that a thread has attempted to wait on an object’s monitor or to notify other threads waiting on an object’s monitor without owning the specified monitor(一个线程尝试等待一个对象的监视器,或者去通知其他正在等待对象监视器线程,却没有指明一个具体的监视器,才会抛出这个异常)
原来是将synchronized
监视到products
对象上了,但调用wait
和notify
方法却不是products
对象,将ProductRepository.java
换成:
public class ProductRepository {
private Vector<Product> products = new Vector<>();
private static final int MAX_NUM = 10;
public void produce(){
synchronized (products){
if (products.size() == MAX_NUM){ //如果仓库已经满了
try {
products.wait(); //让products等待!!!
} catch (InterruptedException e) {
e.printStackTrace();
}
}
//products.size() < MAX_NUM 如果仓库还没有满
Product product = new Product("包子", System.currentTimeMillis());
products.add(product);
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName()+ " 生产了: "+ product+" ,产品仓库当前数量: "+ products.size());
//通知等待的消费者来消费
products.notify();
// products.notifyAll();
}
}
public void consume(){
synchronized (products){
if (products.size() == 0){ //产品仓库空了,等待生产者生产
try {
products.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
Product product = products.firstElement();
products.remove(0);
System.out.println(Thread.currentThread().getName()+ " 消费了: " + product+" ,产品仓库当前数量: "+ products.size());
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
//通知生产者生产
products.notify();
// products.notifyAll();
}
}
}
结果:
producer-A 生产了: Product{name='包子', productNo=1521786975941} ,产品仓库当前数量: 1
consumer-B 消费了: Product{name='包子', productNo=1521786975941} ,产品仓库当前数量: 0
producer-A 生产了: Product{name='包子', productNo=1521786978944} ,产品仓库当前数量: 1
producer-A 生产了: Product{name='包子', productNo=1521786979944} ,产品仓库当前数量: 2
producer-A 生产了: Product{name='包子', productNo=1521786980944} ,产品仓库当前数量: 3
producer-A 生产了: Product{name='包子', productNo=1521786981945} ,产品仓库当前数量: 4
producer-A 生产了: Product{name='包子', productNo=1521786982945} ,产品仓库当前数量: 5
consumer-B 消费了: Product{name='包子', productNo=1521786978944} ,产品仓库当前数量: 4
consumer-B 消费了: Product{name='包子', productNo=1521786979944} ,产品仓库当前数量: 3
一个生产者,多个消费者
只需要在ProductRepository
中将produce
方法中products.notify()
方法换成products.notifyAll()
方法即可
public class ProductRepository {
private Vector<Product> products = new Vector<>();
private static final int MAX_NUM = 10;
public void produce(){
synchronized (products){
if (products.size() == MAX_NUM){ //如果仓库已经满了
try {
products.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
//products.size() < MAX_NUM 如果仓库还没有满
Product product = new Product("包子", System.currentTimeMillis());
products.add(product);
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName()+ " 生产了: "+ product+" ,产品仓库当前数量: "+ products.size());
//通知等待的消费者来消费
// products.notify();
products.notifyAll();
}
}
public void consume(){
synchronized (products){
if (products.size() == 0){ //产品仓库空了,等待生产者生产
try {
products.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
Product product = products.firstElement();
products.remove(0);
System.out.println(Thread.currentThread().getName()+ " 消费了: " + product+" ,产品仓库当前数量: "+ products.size());
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
//通知生产者生产
products.notify();
// products.notifyAll();
}
}
}
测试:
public class ProductorConsumerTest {
/**
* 一个生产者,多个消费者
* @throws InterruptedException
*/
public static void oneProducerAndMoreConsumer() throws InterruptedException {
ProductRepository repository = new ProductRepository();
Consumer consumer = new Consumer(repository);
Consumer consumer2 = new Consumer(repository);
Producer producer = new Producer(repository);
Thread t1 = new Thread(producer,"producer-A");
Thread t2 = new Thread(consumer,"consumer-B");
Thread t3 = new Thread(consumer,"consumer-C");
t1.start();
t2.start();
t3.start();
t1.join();
t2.join();
t3.join();
}
public static void main(String[] args) throws InterruptedException {
// oneProducerAndOneConsumer();
oneProducerAndMoreConsumer();
// moreProducerAndMoreConsumer();
}
}
- 结果:
producer-A 生产了: Product{name='包子', productNo=1521787226868} ,产品仓库当前数量: 1
producer-A 生产了: Product{name='包子', productNo=1521787227868} ,产品仓库当前数量: 2
producer-A 生产了: Product{name='包子', productNo=1521787228868} ,产品仓库当前数量: 3
producer-A 生产了: Product{name='包子', productNo=1521787229868} ,产品仓库当前数量: 4
producer-A 生产了: Product{name='包子', productNo=1521787230868} ,产品仓库当前数量: 5
producer-A 生产了: Product{name='包子', productNo=1521787231868} ,产品仓库当前数量: 6
producer-A 生产了: Product{name='包子', productNo=1521787232868} ,产品仓库当前数量: 7
producer-A 生产了: Product{name='包子', productNo=1521787233868} ,产品仓库当前数量: 8
producer-A 生产了: Product{name='包子', productNo=1521787234868} ,产品仓库当前数量: 9
producer-A 生产了: Product{name='包子', productNo=1521787235868} ,产品仓库当前数量: 10
consumer-C 消费了: Product{name='包子', productNo=1521787226868} ,产品仓库当前数量: 9
consumer-C 消费了: Product{name='包子', productNo=1521787227868} ,产品仓库当前数量: 8
consumer-B 消费了: Product{name='包子', productNo=1521787228868} ,产品仓库当前数量: 7
consumer-C 消费了: Product{name='包子', productNo=1521787229868} ,产品仓库当前数量: 6
consumer-C 消费了: Product{name='包子', productNo=1521787230868} ,产品仓库当前数量: 5
producer-A 生产了: Product{name='包子', productNo=1521787246869} ,产品仓库当前数量: 6
多个生产者,多个消费者
同样只需要修改ProductRepository
中的consumer
方法中的products.notity()
为products.notifyAll()
,通知所有的生产者
public class ProductRepository {
private Vector<Product> products = new Vector<>();
private static final int MAX_NUM = 10;
public void produce(){
synchronized (products){
if (products.size() == MAX_NUM){ //如果仓库已经满了
try {
products.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
//products.size() < MAX_NUM 如果仓库还没有满
Product product = new Product("包子", System.currentTimeMillis());
products.add(product);
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName()+ " 生产了: "+ product+" ,产品仓库当前数量: "+ products.size());
//通知等待的消费者来消费
// products.notify();
products.notifyAll();
}
}
public void consume(){
synchronized (products){
if (products.size() == 0){ //产品仓库空了,等待生产者生产
try {
products.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
Product product = products.firstElement();
products.remove(0);
System.out.println(Thread.currentThread().getName()+ " 消费了: " + product+" ,产品仓库当前数量: "+ products.size());
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
//通知生产者生产
// products.notify();
products.notifyAll();
}
}
}
测试:
public class ProductorConsumerTest {
/**
* 多个生产者,多个消费者
* @throws InterruptedException
*/
public static void moreProducerAndMoreConsumer() throws InterruptedException {
ProductRepository repository = new ProductRepository();
Consumer consumer = new Consumer(repository);
Consumer consumer1 = new Consumer(repository);
Producer producer = new Producer(repository);
Producer producer1 = new Producer(repository);
Thread t1 = new Thread(producer,"producer-A");
Thread t2 = new Thread(consumer,"consumer-B");
Thread t3 = new Thread(consumer1,"consumer-C");
Thread t4 = new Thread(producer1,"producer-D");
t1.start();
t4.start();
t2.start();
t3.start();
t1.join();
t4.join();
t2.join();
t3.join();
}
public static void main(String[] args) throws InterruptedException {
// oneProducerAndOneConsumer();
// oneProducerAndMoreConsumer();
moreProducerAndMoreConsumer();
}
}
结果:
producer-A 生产了: Product{name='包子', productNo=1521787607751} ,产品仓库当前数量: 1
producer-A 生产了: Product{name='包子', productNo=1521787608752} ,产品仓库当前数量: 2
producer-A 生产了: Product{name='包子', productNo=1521787609752} ,产品仓库当前数量: 3
producer-A 生产了: Product{name='包子', productNo=1521787610752} ,产品仓库当前数量: 4
producer-A 生产了: Product{name='包子', productNo=1521787611753} ,产品仓库当前数量: 5
producer-A 生产了: Product{name='包子', productNo=1521787612753} ,产品仓库当前数量: 6
producer-A 生产了: Product{name='包子', productNo=1521787613753} ,产品仓库当前数量: 7
producer-A 生产了: Product{name='包子', productNo=1521787614753} ,产品仓库当前数量: 8
producer-D 生产了: Product{name='包子', productNo=1521787615753} ,产品仓库当前数量: 9
producer-D 生产了: Product{name='包子', productNo=1521787616753} ,产品仓库当前数量: 10
consumer-C 消费了: Product{name='包子', productNo=1521787607751} ,产品仓库当前数量: 9
consumer-B 消费了: Product{name='包子', productNo=1521787608752} ,产品仓库当前数量: 8
consumer-B 消费了: Product{name='包子', productNo=1521787609752} ,产品仓库当前数量: 7
consumer-B 消费了: Product{name='包子', productNo=1521787610752} ,产品仓库当前数量: 6
consumer-C 消费了: Product{name='包子', productNo=1521787611753} ,产品仓库当前数量: 5
consumer-C 消费了: Product{name='包子', productNo=1521787612753} ,产品仓库当前数量: 4
consumer-C 消费了: Product{name='包子', productNo=1521787613753} ,产品仓库当前数量: 3