经典案例:生产者和消费者

    科技2022-07-12  116

    经典案例:生产者和消费者

    文章目录

    经典案例:生产者和消费者一、什么是生产者和消费者?二、如何解决一个生产者与消费者问题主要三种解决方式:1.wait()与notify()方法


    一、什么是生产者和消费者?

    生产者与消费者问题是多线程同步的一个经典问题。生产者和消费者同时使用一块缓冲区,生产者生产商品放入缓冲区,消费者从缓冲区中取出商品。我们需要保证的是,当缓冲区满时,生产者不可生产商品;当缓冲区为空时,消费者不可取出商品。

    二、如何解决一个生产者与消费者问题

    主要三种解决方式:

    wait()与notify()方法

    Lock与Condition机制

    BlockingQueue阻塞队列

    1.wait()与notify()方法

    wait()方法使用条件: wait():一旦执行此方法,当前线程就进入阻塞状态,并释放同步监视器。

    当生产产品数量满时,调用wait()方法,使得生产者释放锁,当前线程阻塞,消费者线程可以获得锁。当产品数量为空时,调用wait()方法,使得消费者释放锁,当前线程阻塞,生产者线程可以获得锁。

    notify()方法使用条件: notify():一旦执行此方法,就会唤醒被wait的一个线程。如果有多个线程被wait,就唤醒优先级高的那个。

    如果刚执行的是消费者,那么产品数量为0,就执行wait()方法等待。那么在执行生产者时,只要生产一个产品就会通过notify()方法唤醒消费者,让消费者来消费产品。如果生产者生产产品过快,消费者来不及消费,并且到达产品上限。那么生产者就执行wait()方法等待。在消费者消费一个产品就会通过notify()方法唤醒生产者,让生产者生产产品。

    代码如下:

    //调度类 public class Clerk { //共享资源 产品数量 private static int productCount = 0; //生产产品 //必须加上同步方法,不然两个线程会产生线程安全问题 public synchronized void produceProduct(){ if (productCount < 20){ productCount++; System.out.println(Thread.currentThread().getName() + ":开始生产第" + productCount + "个产品"); //唤醒等待的消费者 notify(); }else { //等待 try { //产品数量满了,进入等待 wait(); System.out.println("生产满了奥,我要休息一下"); } catch (InterruptedException e) { e.printStackTrace(); } } } //消费产品 public synchronized void consumeProduct(){ if (productCount > 0){ System.out.println(Thread.currentThread().getName() + ":开始消费第" + productCount + "个产品"); productCount--; //唤醒等待的生产者 notify(); }else { try { //产品数量为空,进入等待 wait(); System.out.println("商品没了奥,我要休息一下"); } catch (InterruptedException e) { e.printStackTrace(); } } } } //生产者 public class Producer extends Thread { private Clerk clerk; public Producer(Clerk clerk){ this.clerk = clerk; } @Override public void run() { System.out.println(getName() + ":开始生产产品....."); while (true){ try { Thread.sleep(100); } catch (InterruptedException e) { e.printStackTrace(); } clerk.produceProduct(); } } } //消费者 public class Consumer extends Thread { private Clerk clerk; public Consumer(Clerk clerk) { this.clerk = clerk; } @Override public void run() { System.out.println(getName() + ":开始消费产品....."); while (true){ try { Thread.sleep(200); } catch (InterruptedException e) { e.printStackTrace(); } clerk.consumeProduct(); } } } //测试类 模拟两个生产者,两个消费者 public class Test { public static void main(String[] args) { Clerk clerk = new Clerk(); Producer p1 = new Producer(clerk); p1.setName("生产者1"); Producer p2 = new Producer(clerk); p2.setName("生产者2"); Consumer c1 = new Consumer(clerk); c1.setName("消费者1"); Consumer c2 = new Consumer(clerk); c2.setName("消费者2"); p1.start(); p2.start(); c1.start(); c2.start(); } }

    运行结果如下:

    Processed: 0.009, SQL: 8