2025年阻塞队列的实现(阻塞队列实现java)

阻塞队列的实现(阻塞队列实现java)p id main toc strong 目录 strong p 一 阻塞队列的特点 二 生产者 消费者 存在问题 三 阻塞队列 Java 实现 属性 方法 put 方法 生产者 线程专门调用的方法

大家好,我是讯享网,很高兴认识大家。



 <p id="main-toc"><strong>目录</strong></p> 

讯享网

一、阻塞队列的特点 

二、生产者,消费者

   存在问题:

三、阻塞队列,Java实现 

属性:

方法:

①put方法:"生产者"线程专门调用的方法。

 ②get方法:"消费者"线程专门调用的方法。

执行顺序分析:(图解)

在我们上图的代码当中,如果把while改成if,那么就会存在一个问题:wait()被唤醒之后,此时的if条件,一定不成立了吗?

 如图 :

四、JUC当中的阻塞队列      


阻塞队列,也是一种先进先出的数据结构。和普通的队列(Queue)对比,它新增了两个功能:

       ①如果队列为空,执行出队列,按照Queue的规则,会抛出异常。但是在阻塞队列当中,会发生阻塞。直到有其他线程执行入队列的操作。


       ②如果队列满了,再执行入队列,那么执行入队列的线程会发生阻塞等待。直到有其他线程执行出队列的操作


    在并发编程当中,生产者就是生产数据的线程,消费者就是消费数据的线程。


       如果生产数据的线程处理速度比较快,而消费数据的线程处理速度比较慢,那么生产者将会等待消费者消费完成之后,才能继续生产数据。

       反之,如果生产数据的线程生产比较慢,消费数据的线程消费数据比较快,那么消费数据的线程将需要等待生产数据的线程生产完毕之后,才可以继续消费。

        从以上的场景可以看出生产者和消费者之间的耦合度还是比较高的,因此,就引入了阻塞队列,来降低生产者和消费者之间的耦合度。


   解决问题——引入生产者消费者模式


讯享网


生产者和消费者之间,是通过一个容器来解决生产者和消费者之间的强耦合问题。

由上图可以参考得出:生产者仅仅负责生产数据,消费者仅仅负责获取/消费数据,生产者和消费者之间并没有直接通信,而是通过一个阻塞队列之间通信。


生产者仅仅负责把数据生产完成之后放入到阻塞队列当中,消费者仅仅负责把数据取出来,然后供自己使用。

       也就是说,生产者把数据生产出来之后,直接把数据放到阻塞队列当中,无需等待消费者获取。

       消费者需要获取数据的时候,直接从阻塞队列当中获取,无需等待生产者生产数据,这就是生产者消费者模式


     ①此处考虑需要使用一个数组来实现。

     ②需要定义一个头指针,一个尾指针。

     ③size属性记录队列当中的实际存储个数。


     ①put方法:"生产者"线程专门调用的方法。

     往阻塞队列当中存放元素。

     当队列满的时候,如果仍然有线程调用put方法,那么会进入WAITING状态。

     直到有"消费者"线程尝试从队列当中取出数据,然后把阻塞的"生产者“线程给唤醒。


 ②get方法:"消费者"线程专门调用的方法。

     取出阻塞队列当中的元素。

     当阻塞队列为空的时候,如果仍然有线程调用get方法,那么也会进入WAITING状态。

     直到有“生产者”线程尝试往线程当中存放数据,存放之后唤醒“消费者”线程。

 


执行顺序分析:(图解)


在我们上图的代码当中,如果把while改成if,那么就会存在一个问题:wait()被唤醒之后,此时的if条件,一定不成立了吗?


 如图 :

      在我们的代码当中,这里其实确实是被唤醒之后,if语句一定不成立了。if和while都可以。

      原因:在我们的代码设计当中,put()和get()方法都是同步方法,也就是:

      当队列为的时候,如果"生产者"想继续往队列当中存放元素,会因为条件size==elem.length满足而进入到if语句以内,调用wait()方法进入阻塞等待的状态。

      当被唤醒的时候,一定是要等“消费者”取出元素之后,由“消费者”来唤醒正在wait()的线程


       当队列为空的时候,同理。


       那么,可以理解为:在上面的代码(put方法)当中,"生产者"在被唤醒之前,已经由"消费者"取出了元素,破环了size==elem.length这个条件了,因此不需要再使用while循环的语句重复判断一次了。


       但是,看一下wait()方法的Object类的注释:

  

        因此,在使用形如:      

讯享网

         这样的语句时候,应当改成:

 
                  

       确保wait()被唤醒之前,已经满足了条件。


 

      常见的阻塞队列有:

讯享网 LinkedBlockingQueue,底层是一个链表实现的。 
 ArrayBlockingQueue,底层是一个数组实现的。 
讯享网 PriorityBlockingQueue,底层是一个优先级队列(堆)实现的。要求存放的元素不可以是空的,一定是可以比较的。

       代码实现(链表的阻塞队列)

     

    观察运行结果:

   

    可以看到,线程一直没有结束,一直阻塞。

     

   

     

  


小讯
上一篇 2025-04-29 17:43
下一篇 2025-04-25 22:49

相关推荐

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容,请联系我们,一经查实,本站将立刻删除。
如需转载请保留出处:https://51itzy.com/kjqy/160646.html