/** * Created by butter on 16-11-16. */
/** * * 生产者与消费者模型中,要保证以下几点: * 1 同一时间内只能有一个生产者生产 生产方法加锁sychronized * 2 同一时间内只能有一个消费者消费 消费方法加锁sychronized * 3 共享空间空时消费者不能继续消费 消费前循环判断是否为空,空的话将该线程wait,释放锁允许其他同步方法执行 * 4 共享空间满时生产者不能继续生产 生产前循环判断是否为满,满的话将该线程wait,释放锁允许其他同步方法执行 * */
/** * * 生产者: 一直生产,直到生产完10个 * 在生产过程中,如果库存中存满(1个)则停止生产(由clerk控制) * */
class Producer implements Runnable{
private Clerk clerk;
public Producer(Clerk clerk) {
this.clerk = clerk;
}
@Override
public void run() {
System.out.println("Producer making...");
for (int product = 1; product <= 1000 ; product++) {
try {
clerk.setProdect(product);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
/** * 消费者:不断消费,直到消费10个 * 消费过程中,如果库存有货则消费,没货等待(clerk中wait()) */
class Consumer implements Runnable{
private Clerk clerk;
public Consumer(Clerk clerk) {
this.clerk = clerk;
}
@Override
public void run() {
System.out.println("Consumer buying...");
for (int i = 1; i <= 1000; i++) {
try {
clerk.getProdect();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
/** * 售货员: 负责控制库存,如果库存没货:通知生产者开始生产(notify), 并且通知消费者等待(wait) * ,如果库存有货:通知生产者停止生产(wait), 并且通知消费者开始消费(notify) * notify() / notifyall() :通知 实质上相当于 唤醒 * 加synchronized 为了保证,同一时刻只有一个生产者在生产,只有一个消费者在消费 * */
class Clerk{
private int product = -1;
public synchronized void setProdect(int product) throws InterruptedException {
waitIfFull();
this.product = product;
System.out.println("producer make :" + product);
notify();
}
public synchronized int getProdect() throws InterruptedException {
waitIfEmpty();
int p = this.product;
System.out.println("Consumer get :" + p);
this.product = -1;
notify();
return p;
}
private synchronized void waitIfEmpty() throws InterruptedException {
if(product == -1){
System.out.println("~~~~~~~consumer wait");
wait();
}
}
private synchronized void waitIfFull() throws InterruptedException {
if(product != -1){
System.out.println("~~~~~~~producer wait");
wait();
}
}
}
/** * 主类 */
public class Demo_ProducerComsumer {
public static void main(String[] args) {
Clerk clerk = new Clerk();
new Thread(new Producer(clerk)).start();
new Thread(new Consumer(clerk)).start();
}
}