Java 并发 多线程: 生产者消费者模式
注意事项
无论是使用 synchronized 关键字,还是使用 ReentrantLock 都要注意使用的“锁对象”都要是同一个。
Clerk 类
package pers.xuelei.learningJava.threads.producerAndConsumer;
import static java.lang.Thread.*;
public class Clerk {
private int productCount;
Clerk(){
productCount = 0;
}
/**
* 生产产品
*/
public synchronized void produce(){
while(productCount >= 20) {
System.out.println("生产者生产过剩了,消费者快点消费!");
System.out.print("\n");
//一旦产品数量大于20就暂时停止生产,阻塞在这里
try {
wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
System.out.println(currentThread().getName() + "第" + productCount + "个产品生产完毕");
productCount++;
try {
sleep(10);
} catch (InterruptedException e) {
e.printStackTrace();
}
notifyAll(); //一旦对共享数据变量进行了修改,即共享数据状态发生了变化,那么就应该唤醒
}
/**
* 消费产品
*/
public synchronized void consume(){
while( productCount == 0 ){ //一旦商品数量减少为0,那么便立刻停止消费,等待生产者生产,阻塞在这里
System.out.println("消费者消费完了,生产者快点生产!");
System.out.print("\n");
try {
wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
System.out.println(currentThread().getName() + "第" + productCount + "个产品被消费");
productCount--;
try {
sleep(20);
} catch (InterruptedException e) {
e.printStackTrace();
}
notifyAll();
}
}
Producer And Consumer
package pers.xuelei.learningJava.threads.producerAndConsumer;
class Producer implements Runnable{
private Clerk clerk;
Producer(){}
Producer(Clerk aclerk){
clerk = aclerk;
}
@Override
public void run() {
System.out.println("开始生产产品……");
while (true)
clerk.produce();
}
}
class Consumer implements Runnable{
private Clerk clerk;
Consumer(){}
Consumer(Clerk aclerk){
clerk = aclerk;
}
@Override
public void run() {
System.out.println("开始消费产品……");
while (true)
clerk.consume();
}
}
public class ProducerAndConsumer {
public static void main(String[] args){
Clerk aClerk = new Clerk();
Producer aProducer = new Producer(aClerk);
Consumer aConsumer = new Consumer(aClerk);
Thread proThread = new Thread(aProducer);
proThread.setName("Producer Thread");
Thread conThread = new Thread(aConsumer);
conThread.setName("Consumer Thread");
proThread.start();
conThread.start();
}
}