java多线程通信的经典例题:生产者消费者问题

java多线程有很多经典例题,比如窗口售票问题,生产消费问题。今天就在这里详细讲一下生产者消费者问题:

问题描述:
生产者(producer)将商品交给店员(Clerk),而消费者(Customer)从店员处取走商品,店员的货架上只能放一定数量的商品,如果生产者试图生产更多的商品,店员会叫生产者停一下,如果货架上有空位放商品再通知消费者继续生产。如果没有商品了,会告诉消费者等一下,如果店中有商品了再通知消费者来取走商品。

看到这个问题,我们不要去急着写代码,先来分析一下该题中会出现的多线程的知识点:
1.是否要用到多线程?
这是肯定的,消费和生产的动作可以同时进行,所以会有一个生产者线程,消费者线程。
2.是否要共享数据?是否涉及到了线程安全问题?
是,商品是生产者和消费者共享的数据。涉及到了线程安全问题,需要用同步机制(三种)来解决。
3.是否涉及到线程通信?
是,货架空是需要通知生产者生产商品,货架有商品时通知消费者来取走商品。

分析过了之后,我们就可以着手写代码了
本题中可划分3个类,即商品类(Clerk),生产者(Producer),消费者(Customer)

商品类:需要统计和显示商品的数量,有生产商品的方法,消费商品的方法
生产者:提供线程,当货架未满时不断循环提供商品。
消费者:提供线程,当货架有商品时不断循环消费商品。

代码如下:

public class Test {
    
    
	public static void main(String[] args) {
    
    
		Clerk clerk=new Clerk();
		Producer p1=new Producer(clerk);
		p1.setName("生产者1");
		
		Customer c1=new Customer(clerk);
		c1.setName("消费者1");
		
		p1.start();
		c1.start();
	}
}
/*
 * 商品类
 */
class Clerk{
    
    
	private int ProductCount=0;

	//生产商品
	public synchronized void ProduceProduct() {
    
    
		// TODO Auto-generated method stub
		if(ProductCount<20) {
    
    
			ProductCount++;
			System.out.println(Thread.currentThread().getName()+"正在生产第"+ProductCount+"个商品");
			notify();
		}else {
    
    
			//等待
			try {
    
    
				wait();
			} catch (InterruptedException e) {
    
    
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}	
	}

	//消费商品
	public synchronized void CustomeProduct() {
    
    
		// TODO Auto-generated method stub
		if(ProductCount>0) {
    
    
			System.out.println(Thread.currentThread().getName()+"正在消费第"+ProductCount+"个商品");
			ProductCount--;
			
			notify();
		}else {
    
    
			//等待
			try {
    
    
				wait();
			} catch (InterruptedException e) {
    
    
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}
	}
}
/*
 * 生产者
 */
class Producer extends Thread{
    
    

	private Clerk clerk;
	
	public Producer(Clerk clerk) {
    
    
		super();
		this.clerk = clerk;
	}

	@Override
	public void run() {
    
    
		// TODO Auto-generated method stub
		System.out.println(Thread.currentThread().getName()+"开始生产商品...");
		
		while(true) {
    
    
			
			try {
    
    
				Thread.sleep(100);
			} catch (InterruptedException e) {
    
    
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
			
			clerk.ProduceProduct();
		}
	}
}
/*
 * 消费者
 */ 
class Customer extends Thread{
    
    
	private Clerk clerk;

	public Customer(Clerk clerk) {
    
    
		super();
		this.clerk = clerk;
	}

	@Override
	public void run() {
    
    
		// TODO Auto-generated method stub
		
		System.out.println(Thread.currentThread().getName()+"开始消费商品...");
		
		while(true) {
    
    
			
			try {
    
    
				sleep(100);
			} catch (InterruptedException e) {
    
    
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
			clerk.CustomeProduct();
		}
	}
}

此时运行后你会发现生产者每生产一个商品很快就会被消费者拿走,货架商的数量一直保持在2个以内。
这个问题,只需要把消费者的睡眠时间加长一些即可,也或者可以多增加一些消费者,更贴近实际。

猜你喜欢

转载自blog.csdn.net/qq_45273552/article/details/107029370