操作系统的多生产者和多消费者是个经典的多线程场景,如何用Java模拟呢?
首先定义资源类:
/**
* 生产者消费者模式: 多生产者和多消费者,用数组实现
* 共享资源,以生产烤鸭为例
*/
class BoundedBuffer {
final Lock lock = new ReentrantLock();//锁
//互斥变量
final Condition notFull = lock.newCondition(); //生产者
final Condition notEmpty = lock.newCondition(); //消费者
final Object[] items = new Object[100];//缓冲区
//指针putptr: 生产到第几只鸭子, 指针takeptr: 消费到第几只鸭子 , 指针count: 当前有几只鸭子
public int putptr, takeptr, count;
/**
* 生产
*/
public void put(Object x) throws InterruptedException {
lock.lock();
try {
//如果生产者把缓冲区填满了就不再生产,等待
while (count == items.length)
notFull.await();
items[putptr] = x;
if (++putptr == items.length) putptr = 0;//生产到第100只鸭子的位置,从头重新开始生产
++count;
notEmpty.signal();//唤醒消费者
} finally {
lock.unlock();
}
}
/**
* 消费
*/
public Object take() throws InterruptedException {
lock.lock();
try {
//如果缓冲区没有鸭子可以吃,消费者就等待生产者生鸭子
while (count == 0)
notEmpty.await();
Object x = items[takeptr];
if (++takeptr == items.length) takeptr = 0;//消费到第100只鸭子的位置,从0开始消费
--count;
notFull.signal();//唤醒生产者
return x;
} finally {
lock.unlock();
}
}
}
然后构造生产者和消费者线程:
生产者线程:
/**
* 生产者线程
*/
class Producer implements Runnable
{
BoundedBuffer buf;
Producer(BoundedBuffer buf)
{
this.buf = buf;
}
public void run()
{
while(true)
{
Object obj = new Object();
try{buf.put(obj);}catch(InterruptedException ex){}
System.out.println(".-------生产第几只烤鸭: "+buf.putptr+"=============="+Thread.currentThread().getName());
}
}
}
消费者线程:
/**
* 消费者线程
*/
class Consumer implements Runnable
{
BoundedBuffer buf;
Consumer(BoundedBuffer buf)
{
this.buf = buf;
}
public void run()
{
while(true)
{
try{ buf.take();}catch(InterruptedException ex){}
System.out.println(Thread.currentThread().getName()+".-----消费第几只烤鸭: -------------------->"+buf.takeptr);
}
}
}
/**生产者消费者模式: 多生产者和多消费者,用数组实现*/
class BoundedBufferDemo
{
public static void main(String[] args)
{
BoundedBuffer buf = new BoundedBuffer();
Producer p1 =new Producer(buf);
Producer p2 =new Producer(buf);
Consumer c1 = new Consumer(buf);
Consumer c2 = new Consumer(buf);
Thread th_p1 = new Thread(p1);
Thread th_p2 = new Thread(p2);
Thread th_c1 = new Thread(c1);
Thread th_c2 = new Thread(c2);
th_p1.start();
th_p2.start();
th_c1.start();
th_c2.start();
}
}