被遗忘的凉白开
文章22
标签34
分类3
面试官:看你简历上写着熟悉多线程,设计一个符合生产者和消费者问题的程序

面试官:看你简历上写着熟悉多线程,设计一个符合生产者和消费者问题的程序

使用notify/notifyAll、wait实现一个生产者消费者模式面试中也是挺常见的,本文通过标准范式和一个子弹发射和上膛的例子,讲述了线程之间是怎么协作的!希望对XDM有帮助!

这是我参与更文挑战的第10天,活动详情查看: 更文挑战

1、wait()和notifyAll()、notify()

线程间的协作,等待和通知机制,我们说的线程间的协作是用这两个方法,但是我们说的wait和notifyAll方法不是Thread类里特有的方法哦!它们是Object里面的方法!

image.png

image.png

2、等待通知范式

waitf范式

image.png

这个都不用我写了,JDK源码里wait方法的注释上写着呢
wait方法一定是写到同步代码块里的,而且调用对象必须是当前锁对象,如果不这样写,它会报错给你看的

notifyAll/notify范式

image.png

和wait一样也是写到同步代码块里 的,而且调用对象必须是当前锁对象

jdk为什么要这样写,咱们从下面的代码的例子就知道了,它们是怎么协作的了

3、生产者消费者程序实现

采用多线程技术,例如wait/notify,设计实现一个符合生产者和消费者问题的程序,对某一个对象(枪膛)进行操作,其最大容量是20颗子弹,生产者线程是一个压入线程,它不断向枪膛中压入子弹,消费者线程是一个射出线程,它不断从枪膛中射出子弹。

public class Gun {
    private int bulletNumber=0;//枪膛的子弹数
    public synchronized void biuBullet(){
        while(bulletNumber<1){//如果弹夹没子弹,就进行等待
            try {
                wait();
            }catch (InterruptedException e){
                e.printStackTrace();
            }

        }
        bulletNumber--;
        System.out.println("发射了一个子弹 当前子弹数:"+bulletNumber);
        notifyAll();//通知装弹者装弹

    }
    public synchronized void reloadBuillet(){
        while(bulletNumber>19){
            try {
                wait();
            }catch (InterruptedException e){
                e.printStackTrace();
            }
        }
        bulletNumber++;
        System.out.println("压入了一个子弹 当前子弹数:"+bulletNumber);
        notifyAll();//通知biubiu
    }
}

这样就能保证我发射的线程发射的时候如果弹夹里没子弹了,会进入wait状态,如果它进入等待状态,说明子弹数一定小于20,则装弹的线程的条件一定满足看,所以肯定会进行装弹,然后通知进入等待状态的发射线程进行发射

public class TestGun {
    static Gun gun=new Gun();
   static class BiuBulletThread extends Thread{
       @Override
       public void run() {
           gun.biuBullet();
       }
   }
   static class ReloadBulletThread extends Thread{
       @Override
       public void run() {
           gun.reloadBuillet();
       }
   }

    public static void main(String[] args) throws InterruptedException {

            for(int i=0;i<3;i++){
                new TestGun.BiuBulletThread().start();
            }
            for(int i=0;i<3;i++){
                new TestGun.ReloadBulletThread().start();
            }

            Thread.sleep(1000);

        }

}

运行结果
image.png

由上可知,我们生产者,消费者的锁必须得是同一把锁,不然同时进行消费和生产,就会乱套了,
我们还能知道什么呢?

wati的时候当前线程会释放锁,让其他线程再去竞争这把锁,而notify方法不会释放锁,只有通知的这个线程所有任务执行完之后才会释放锁

wait肯定会释放锁,如果不释放锁,生产者就不会抢到这把锁,也就不生产,也就不通知,wait就会一直wait
以上就是线程之间协作的一个例子

4、总结

使用notify/notifyAll、wait实现一个生产者消费者模式面试中也是挺常见的,本文通过标准范式和一个子弹发射和上膛的例子,讲述了线程之间是怎么协作的!希望对XDM有帮助!

本文作者:被遗忘的凉白开
本文链接:http://amszlk.com/2021/06/24/mian-shi-guan-kan-ni-jian-li-shang-xie-zhao-shou-xi-duo-xian-cheng-she-ji-yi-ge-fu-he-sheng-chan-zhe-he-xiao-fei-zhe-wen-ti-de-cheng-xu/
版权声明:本文采用 CC BY-NC-SA 3.0 CN 协议进行许可