Java中ArrayBlockingQueue和LinkedBlockingQueue

 更新时间:2022年09月02日 09:25:22   作者:乐活青年  
这篇文章主要介绍了Java中ArrayBlockingQueue和LinkedBlockingQueue,文章围绕主题展开详细的内容介绍,具有一定的参考价值,需要的朋友可以参考一下

ArrayBlockingQueue

用数组实现的有界阻塞队列。此队列按照先进先出(FIFO)的原则对元素进行排序。默认情况下不保证访问者公平的访问队列,所谓公平访问队列是指阻塞的所有生产者线程或消费者线程,当队列可用时,可以按照阻塞的先后顺序访问队列,即先阻塞的生产者线程,可以先往队列里插入元素,先阻塞的消费者线程,可以先从队列里获取元素。通常情况下为了保证公平性会降低吞吐量。

LinkedBlockingQueue

基于链表的阻塞队列,同ArrayListBlockingQueue类似,此队列按照先进先出(FIFO)的原则对元素进行排序,其内部也维持着一个数据缓冲队列(该队列由一个链表构成),当生产者往队列中放入一个数据时,队列会从生产者手中获取数据,并缓存在队列内部,而生产者立即返回;只有当队列缓冲区达到最大值缓存容量时(LinkedBlockingQueue可以通过构造函数指定该值),才会阻塞生产者队列,直到消费者从队列中消费掉一份数据,生产者线程会被唤醒,反之对于消费者这端的处理也基于同样的原理。而LinkedBlockingQueue之所以能够高效的处理并发数据,还因为其对于生产者端和消费者端分别采用了独立的锁来控制数据同步,这也意味着在高并发的情况下生产者和消费者可以并行地操作队列中的数据,以此来提高整个队列的并发性能。
作为开发者,我们需要注意的是,如果构造一个LinkedBlockingQueue对象,而没有指定其容量大小,LinkedBlockingQueue会默认一个类似无限大小的容量(Integer.MAX_VALUE),这样的话,如果生产者的速度一旦大于消费者的速度,也许还没有等到队列满阻塞产生,系统内存就有可能已被消耗殆尽了。

相同:

  • LinkedBlockingQueue和ArrayBlockingQueue都是可阻塞的队列
  • 内部都是使用ReentrantLock和Condition来保证生产和消费的同步;
  • 当队列为空,消费者线程被阻塞;当队列装满,生产者线程被阻塞;
  • 使用Condition的方法来同步和通信:await()和signal()

不同:

1、锁机制不同

  • LinkedBlockingQueue中的锁是分离的,生产者的锁PutLock,消费者的锁takeLock
  • 而ArrayBlockingQueue生产者和消费者使用的是同一把锁;

2、底层实现机制也不同

  • LinkedBlockingQueue内部维护的是一个链表结构。
  • 在生产和消费的时候,需要创建Node对象进行插入或移除,大批量数据的系统中,其对于GC的压力会比较大。
  • 而ArrayBlockingQueue内部维护了一个数组
  • 在生产和消费的时候,是直接将枚举对象插入或移除的,不会产生或销毁任何额外的对象实例。

3、构造时候的区别

  • LinkedBlockingQueue有默认的容量大小为:Integer.MAX_VALUE,当然也可以传入指定的容量大小
  • ArrayBlockingQueue在初始化的时候,必须传入一个容量大小的值

4、执行clear()方法

  • LinkedBlockingQueue执行clear方法时,会加上两把锁

 5、统计元素的个数

  • LinkedBlockingQueue中使用了一个AtomicInteger对象来统计元素的个数,ArrayBlockingQueue则使用int类型来统计元素。

补充(Java些操使线程释放锁资源)

1.sleep()方法

在指定时间内让当前正在执行的线程暂停执行,但不会释放“锁标志”。不推荐使用。

sleep()使当前线程进入阻塞状态,在指定时间内不会执行。

2.wait()方法

在其他线程调用对象的notify或notifyAll方法前,导致当前线程等待。线程会释放掉它所占有的“锁标志”,从而使别的线程有机会抢占该锁。

当前线程必须拥有当前对象锁。如果当前线程不是此锁的拥有者,会抛出IllegalMonitorStateException异常。

唤醒当前对象锁的等待线程使用notify或notifyAll方法,也必须拥有相同的对象锁,否则也会抛出IllegalMonitorStateException异常。

waite()和notify()必须在synchronized函数或synchronized block中进行调用。如果在non-synchronized函数或non-synchronized block中进行调用,虽然能编译通过,但在运行时会发生IllegalMonitorStateException的异常。

3.yield方法

暂停当前正在执行的线程对象。

yield()只是使当前线程重新回到可执行状态,所以执行yield()的线程有可能在进入到可执行状态后马上又被执行。

yield()只能使同优先级或更高优先级的线程有执行的机会。

4.join方法

等待该线程终止。

等待调用join方法的线程结束,再继续执行。如:t.join();//主要用于等待t线程运行结束,若无此句,main则会执行完毕,导致结果不可预测。

join()底层就是调用wait()方法的,wait()释放锁资源,故join也释放锁资源

  • 1.sleep会使当前线程睡眠指定时间,不释放锁
  • 2.yield会使当前线程重回到可执行状态,等待cpu的调度,不释放锁
  • 3.wait会使当前线程回到线程池中等待,释放锁,当被其他线程使用notify,notifyAll唤醒时进入可执行状态
  • 4.当前线程调用 某线程.join()时会使当前线程等待某线程执行完毕再结束,底层调用了wait,释放锁

到此这篇关于Java中ArrayBlockingQueue和LinkedBlockingQueue的文章就介绍到这了,更多相关Java ArrayBlockingQueue内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • Java微信公众平台开发(10) 微信自定义菜单的创建实现

    Java微信公众平台开发(10) 微信自定义菜单的创建实现

    这篇文章主要为大家详细介绍了Java微信公众平台开发第十步,微信自定义菜单的创建实现,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2017-04-04
  • SWT(JFace) 体验之FontRegistry

    SWT(JFace) 体验之FontRegistry

    测试代码如下:
    2009-06-06
  • 浅谈Java中的URL和URLConnection

    浅谈Java中的URL和URLConnection

    这篇文章主要介绍了浅谈Java中的URL和URLConnection,URL代表的是一种资源,它使用的是统一资源定位格式, 其实我们还可以用URL来构造对象的,java中有大量的构造函数允许使用一个个的分串来指定URL,需要的朋友可以参考下
    2023-08-08
  • Mybatis返回单个实体或者返回List的实现

    Mybatis返回单个实体或者返回List的实现

    这篇文章主要介绍了Mybatis返回单个实体或者返回List的实现,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2020-07-07
  • SpringMVC与Mybatis集合实现调用存储过程、事务控制实例

    SpringMVC与Mybatis集合实现调用存储过程、事务控制实例

    这篇文章主要介绍了SpringMVC与Mybatis集合实现调用存储过程、事务控制实例,有需要的可以了解一下。
    2016-11-11
  • Spring Security LDAP实现身份验证的项目实践

    Spring Security LDAP实现身份验证的项目实践

    在本文中,我们涵盖了“使用 Spring Boot 的 Spring Security LDAP 身份验证示例”的所有理论和示例部分,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2023-08-08
  • myeclipse开发servlet_动力节点Java学院整理

    myeclipse开发servlet_动力节点Java学院整理

    MyEclipse,是在eclipse基础上加上自己的插件开发而成的功能强大的企业级集成开发环境,主要用于Java、Java EE以及移动应用的开发。下面这篇文章主要给大家介绍了关于myeclipse开发servlet的相关资料,需要的朋友可以参考下。
    2017-07-07
  • Java StackOverflowError详解

    Java StackOverflowError详解

    这篇文章主要介绍了Java StackOverflowError详解,本篇文章通过简要的案例,讲解了该项技术的了解与使用,以下就是详细内容,需要的朋友可以参考下
    2021-08-08
  • Java中的跨域和@CrossOrigin注解的作用详解

    Java中的跨域和@CrossOrigin注解的作用详解

    这篇文章主要介绍了Java中的跨域和@CrossOrigin注解的作用详解,跨域,指的是浏览器不能执行其他网站的脚本。它是由浏览器的同源策略造成的,是浏览器对JavaScript施加的安全限制,需要的朋友可以参考下
    2023-12-12
  • Java原生序列化和反序列化代码实例

    Java原生序列化和反序列化代码实例

    这篇文章主要介绍了Java原生序列化和反序列化代码实例,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
    2020-02-02

最新评论