生产者和消费者是多线程经典的问题,生产者和消费者问题的核心是同步的问题,同步问题的核心是要保证同一个资源被多个线程并发访问时的完整性,常用的方法是采用信号或加锁机制,保证资源在任一时刻只能被一个线程访问。这一问题用Java来实现的话主要有4种方式。1.wait()/notify();2.await()/signal(); 3.blockingQuene 4.PipedInputStream/pipedOutputStream
下面分别来实现。
1.利用wait()和notify()来实现
Wait()方法:当缓冲区已空/满时,生产者/消费者停止自己的执行,放弃锁,使自己处于等待状态,让其他线程执行。
Notify()方法:当生产者/消费者向缓冲区放入/取出一个产品时,向其他等待的线程发出可执行的通知,同时放弃锁,使自己处于等待状态。
下面看看代码实现:
首先定义商店类:
package ConsumerAndProducerProblem;
import java.util.LinkedList;
/**
* @author: zhuwei
* @ClassName: 商店类
* @Description: TODO
* @Date: 下午3:58:01
*/
public class Storage
{
//定义仓库最大容量100
private final int MAX_SIZE = 100;
private LinkedList<Object> list= new LinkedList<>();
//生产num个商品
public void produce(int num) throws Exception
{
synchronized(list)
{
//假如仓库容量不足
if(list.size()+num>MAX_SIZE)
{
System.out.println("仓储容量不足");
//线程等待
list.wait();
}
//仓库容量可以容量生产者的生产,则生产
for(int i = 0;i < num;i++)
{
list.add(new Object());
}
System.out.println("生产者生产产品数量为:"+ num);
list.notifyAll();
}
}
//消费num个商品
public void consume(int num) throws Exception
{
synchronized(list)
{
//加入仓库中的商品不能满足消费者的需求,线程等待
if(list.size() < num)
{
System.out.println("仓库中的商品不能满足消费者需求");
list.wait();
}
for(int i = 0;i < num;i++)
{
list.remove();
}
System.out.println("消费者消费商品数量为:"+num);
list.notifyAll();
}
}
}
定义生产者类
package ConsumerAndProducerProblem;
/**
* @author: zhuwei
* @ClassName: 生产者线程
* @Description: TODO
* @Date: 下午3:57:15
*/
public class Consumer implements Runnable
{
//消费商品数量
private int number;
private Storage storage;
public void consume(int num)
{
try
{
storage.consume(num);
} catch (Exception e)
{
// TODO Auto-generatedcatch block
e.printStackTrace();
}
}
public int getNumber()
{
return number;
}
public void setNumber(int number)
{
this.number = number;
}
public Storage getStorage()
{
return storage;
}
public void setStorage(Storage storage)
{
this.storage = storage;
}
@Override
public void run()
{
// TODO Auto-generatedmethod stub
consume(number);
}
}
定义消费者类: