暂无图片
暂无图片
暂无图片
暂无图片
暂无图片

阻塞队列知多少

长夜难眠 2020-07-25
258

点击蓝字

关注不迷途


阻塞队列是并发操作中很重要的数据结构,阻塞队列提供插入阻塞以及取出阻塞。


也就是插入时,队列满了,则阻塞,等队列有空闲位置的时候会被唤醒。


同时从队列中取出元素时,如果队列没有元素,该方法也会被阻塞住,等队列中有元素被插入时,才会被唤醒。


阻塞队列提供几种类型的方法。


阻塞操作:put(e),阻塞插入;take()阻塞取出。


抛异常:add(e),插入时队列满,则抛出异常;remove(),取出时队列没有元素,则抛出异常。


返回特定值:offer(e),返回是否插入成功;poll()返回取出元素,没有元素返回null。


超时返回特定值:offer(e,time,unit),如果插入时没有位置,则阻塞设定的时间,再次唤醒插入,返回是否插入成功;poll(time,unit),如果取出时没有元素,则阻塞一定时间,再次唤醒执行取出动作,返回取出元素,没有元素返回null。


阻塞队列接口为BlockingQueue,那么常用的实现类有哪些呢?


可以划分为有界队列和无界队列。


ArrayBlockingQueue:使用数组实现的有界队列。


LinkedBlockingQueue:使用链表实现的有界队列。


LinkedBlockingDeque:使用双向链表实现的有界队列。


SynchronousQueue:不存储元素的队列,使用put(e)方法会阻塞等待执行take()方法;反之亦然,使用take()方法会阻塞等待put(e)方法。


适合应用在线程之间的通信上。


同时该阻塞队列可以实现公平队列和非公平队列,公平队列使用队列实现,先阻塞的线程先被唤醒。


非公平队列使用栈来实现,后阻塞线程会先被唤醒。


无界队列使用put(e)不阻塞,因为总有空闲空间可以被插入。使用put(e)方法实际上会被调用offer(e)方法


PriorityBlockingQueue:实现优先级的队列,可以自定义compare方法来排序元素。



如果存储的元素实现了Comparable,则使用compareTo方法进行优先级排序。


LinkedTranferQueue:使用链表实现的无界队列。


该队列还提供了transfer()方法和tryTransfer()方法。


transfer(e)方法会把元素传输给需要取出的方法take()或者poll(),如果没有需要取出时,则把元素插入到tail位置,直到被取出才返回。


tryTransfer()方法只是尝试把元素传输给take()或者poll(),如果没有被取出则返回false,不会阻塞等待到被取出。


tryTransfer还可以设置超时时间,如果第一时间没有被取出,可以等待超时,再返回结果。


DelayQueue:这是一个延迟优先级无界阻塞队列。


存储的元素必须实现Delayed接口,实现getDelay(unit)方法和compareTo(delayed)方法。


现实现一个有有效期的会员开卡以及销卡过程。


会员类,实现了Delayed接口,同时存储过期时间。



getDelay(unit)方法返回剩余存活时间,如果等于0,可以被队列移除,注意不能为负数,负数也不能被移除,否则取出操作会被阻塞。


compareTo(delayed)方法对元素进行排序,剩余存活时间短的应该排在前面,实现顺序地销毁过期的会员。



开卡线程每一秒开一张卡,卡过期时间为3s。


销卡线程会循环取出头部元素进行销卡操作。



根据控制台输出可以发现销卡会从3s之后才开始进行销卡操作,因为只有3s后才有会员过期。


DelayQueue可以应用于缓存系统、定时任务调度、订单超时支付取消等场景。



喜欢本篇内容顺便点个在看吧


文章转载自长夜难眠,如果涉嫌侵权,请发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。

评论