基于LinkedBlockingQueue实现的简版的消息队列

前言

最近在精简系统的部署方案,准备再做一个去RibbitMQ的技术方案,于是研究到了java中的LinkedBlockingQueue。

LinkedBlockingDeque 结构

  • LinkedBlockingQueue
  • 我们先看下LinkedBlockingDeque类的关系结构

  • 是不是和我前面文章写的DelayQueue师出同门
  • 还有个很像LinkedBlockingQueue的LinkedBlockingDeque( 双端链表)

  • 同属阻塞队列,区别在于 多了一个Deque,Deque是什么?
  • Queue:队列,特点,先进后出,只提供追加元素到队列末尾和出队列头元素
  • Deque:双端队列,说白了,就是增强了Queue的前后操作,可以前出后出,前入后入

LinkedBlockingQueue

  • 单链表实现,只能从head取元素,从tail添加元素,并且都会加锁
  • 内部采用可重入锁,保证并发下的线程安全
  • LinkedBlockingQueue支持读写分离,读写操作可以并行
  • 提供3个构造器:
// 容量默认为 Integer.MAX_VALUE,思考会存在什么问题?
public LinkedBlockingQueue();
// 指定容量
public LinkedBlockingQueue(int capacity)
// 传入一个容器,容量默认也是 Integer.MAX_VALUE
public LinkedBlockingQueue(Collection<? extends E> c)

提供的方法

操作抛出异常非阻塞,返回boolean可能阻塞设置超时时间
入队列add(e)offer(e)put(e)offer(e,timeout,unit)
出队列remove()poll()take()poll(timeout, unit)
查看元素element()peek()--
  • 带异常抛出的,例如队列被元素填满后,再调用add,则会抛出异常IllegalStateException
  • 非阻塞,返回Boolean,当元素填完满队列后,再调用offer,插入不成功,不会有异常,而是返回false
  • 想实现阻塞功能,调用普通、take,当出现队列拥堵时,会阻塞线程

基于LinkedBlockingQueue实现MQ的思路

  • 利用Spring中的事件发布与订阅+异步方法来实现提供发送消息的API
  • 事件订阅方收到消息后,将消息put进队列
  • 起一个多线程类,实现run方法逻辑,在run中通过死循环对queue进行take()
  • 当队列中没有元素时,take()会阻塞着,当有元素放入时,则会取到头元素
  • 取到元素后,通过消息对象的属性,反射调用到消息监听者的process()方法即可
  • 完善一点:考虑投递或消费失败重试,并且重试多次失败后,考虑持久化到数据库中,便于排查问题或手动重试

可扩展了解

  • ConcurrentLinkedQueue,基于链接节点的无界线程安全队列,无锁非阻塞方式
  • 使用CAS原子指令来处理对数据的并发访问,是非阻塞算法得以实现的基础
  • 具体参看这篇文章:Java并发编程之ConcurrentLinkedQueue详解
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值