java多线程实现生产者与消费者模型
//测试类
public class TestPC {
public static void main(String[] args) {
SynContainer container = new SynContainer();
new Thread(new Productor(container),"生产者线程").start();
new Thread(new Consumer(container),"消费者线程").start();
}
}
//生产者
class Productor implements Runnable{
SynContainer container = null;
Productor(SynContainer container) {
this.container = container;
}
@Override
public void run() {
for (int i = 1; i <= 100; i++) {
container.push(new Product(i),i);
}
}
}
//消费者
class Consumer implements Runnable{
SynContainer container = null;
Consumer(SynContainer container) {
this.container = container;
}
@Override
public void run() {
for (int i = 1; i <= 100; i++) {
container.pop();
}
}
}
//产品
class Product {
int id;
Product(int id) {
this.id = id;
}
}
//容器
class SynContainer {
Product[] pros = new Product[10];
int count = 0;//产品数量
//生产者放入产品
public synchronized void push(Product product,int i) {
if(count == pros.length) {
try {
System.out.println("生产者:放不进去了,先等消费者消费吧");
this.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
System.out.println("生产了第" + i + "个产品");
pros[count] = product;
count++;
this.notifyAll();
}
//消费者消费产品
public synchronized void pop() {
if(count == 0) {
try {
System.out.println("消费者:没东西拿了,先等生产者生产吧");
this.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
count--;
System.out.println("消费了第" + pros[count].id + "个产品");
pros[count] = null;
this.notifyAll();
}
}
/*当synchronized关键字放在普通方法前,锁对象是类实例本身。
上面的代码中,生产者和消费者中的container对象实质上都是测试类中传入的对象,即同一个对象。*/
线程的wait和notifyAll方法的理解:
- obj.wait()方法。obj是被若干线程持有的锁对象,wait方法会阻塞正在持有该锁对象的线程,并释放锁(sleep方法则不会)。在代码中的SynContainer类的push和pop方法都调用了wait方法,当满足条件时,会将对应的线程(生产者or消费者)阻塞并释放锁。
- obj.notifyAll()方法。唤醒所有因未持有obj锁对象而被阻塞的线程,常与wait方法搭配使用实现线程通信效果。notify()方法会随机唤醒等待队列中的一个线程。