Java多线程实现生产者与消费者模型

发布时间 2023-09-27 19:46:11作者: 万里阳光号船长

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方法的理解:

  1. obj.wait()方法。obj是被若干线程持有的锁对象,wait方法会阻塞正在持有该锁对象的线程,并释放锁(sleep方法则不会)。在代码中的SynContainer类的push和pop方法都调用了wait方法,当满足条件时,会将对应的线程(生产者or消费者)阻塞并释放锁。
  2. obj.notifyAll()方法。唤醒所有因未持有obj锁对象而被阻塞的线程,常与wait方法搭配使用实现线程通信效果。notify()方法会随机唤醒等待队列中的一个线程。