阻塞队列的处理方法
阻塞队列实现了 BlockingQueue 接口,并且有多组处理方法。
抛出异常
- add方式是往队列里面添加元素,如果队里队列满了,会抛出异常
- remove方法是删除元素,如果队列里面的不够删除了则抛出异常
- element 方法是返回队列的头部节点,但是并不删除。如果用这个方法去操作一个空队列,会抛出和前面 remove 方法一样的异常:NoSuchElementException
返回结果但不抛出异常
- offer 方法用来插入一个元素,并用返回值来提示插入是否成功。如果添加成功会返回 true,而如果队列已经满了,此时继续调用 offer 方法的话,它不会抛出异常,只会返回一个错误提示:false。
- poll 方法表示移除并返回队列的头节点。如果当队列里面是空的,便会返回 null 作为提示。正因如此,是不允许往队列中插入 null 的,否则没有办法区分返回的 null 是一个提示还是一个真正的元素。
- peek 方法返回队列的头元素但并不删除。如果队列里面是空的,它便会返回 null 作为提示。
阻塞
- put 方法的作用是插入元素。如果队列已满就无法继续插入,这时它既不会立刻返回 false 也不会抛出异常,而是让插入的线程陷入阻塞状态,直到队列里有了空闲空间,此时队列就会让之前的线程解除阻塞状态,并把刚才那个元素添加进去。
- take 方法的作用是获取并移除队列的头结点。通常在队列里有数据的时候会正常取出数据并删除;但是如果执行 take 的时候队列里无数据,则阻塞,直到队列里有数据;一旦队列里有数据了,就会立刻解除阻塞状态,并且取到数据。
抛出异常:add(e) 、remove()、element()
返回结果但不抛出异常:offer(e) 、poll()、peek()
阻塞:put(e) 、take()
JDK 8 中提供了七个阻塞队列
- ArrayBlockingQueue :一个由数组结构组成的有界阻塞队列。
- LinkedBlockingQueue :一个由链表结构组成的无界阻塞队列。
- PriorityBlockingQueue :一个支持优先级排序的无界阻塞队列。
- DelayQueue:一个使用优先级队列实现的无界阻塞队列。
- SynchronousQueue:一个不存储元素的阻塞队列。
- LinkedTransferQueue:一个由链表结构组成的无界阻塞队列。
- LinkedBlockingDeque:一个由链表结构组成的双向阻塞队列。
ArrayBlockingQueue
一个由数组结构组成的有界阻塞队列。初始时就要指定大小,内部用数组存储元素,利用ReentrantLock实现线程安全。初始创建指定容量后,不能再扩容。ArrayBlockingQueue采用全部锁,锁的粒度较大。
ConcurrentLinkedQueue内部也是由单向链表的方式实现,默认存在一个哨兵节点,它是线程安全的无界非阻塞队列,与BlockingQueue不同的是,ConcurrentLinkedQueue通过CAS方式实现线程安全。
LinkedBlockingQueue
一个由链表结构组成的无界阻塞队列。
如果不指定它的初始容量,则默认容量就是整形的最大值Integer.MAX_VALUE,由于容量非常大,LinkedBlockingQueue 也被称作无界队列。
SynchronousQueue
SynchronousQueue 最大的不同之处在于,它的容量为 0,所以没有一个地方来暂存元素,导致每次取数据都要先阻塞,直到有数据被放入;同理,每次放数据的时候也会阻塞,直到有消费者来取。需要注意的是,SynchronousQueue 的容量不是 1 而是 0,因为 SynchronousQueue 不需要去持有元素,它所做的就是直接传递(direct handoff)。由于每当需要传递的时候,SynchronousQueue 会把元素直接从生产者传给消费者,在此期间并不需要做存储,所以如果运用得当,它的效率是很高的。
SynchronousQueue 的 peek 方法永远返回 null
PriorityBlockingQueue
PriorityBlockingQueue 是一个支持优先级的无界阻塞队列,可以通过自定义类实现 compareTo() 方法来指定元素排序规则,或者初始化时通过构造器参数 Comparator 来指定排序规则。同时,插入队列的对象必须是可比较大小的,也就是 Comparable 的,否则会抛出 ClassCastException 异常。
DelayQueue
DelayQueue是一个无界阻塞延迟队列,具有“延迟”的功能。我们可以设定让队列中的任务延迟多久之后执行,比如 10 秒钟之后执行,这在例如“30 分钟后未付款自动取消订单”等需要延迟执行的场景中被大量使用。它是无界队列,放入的元素必须实现 Delayed 接口,而 Delayed 接口又继承了 Comparable 接口,所以自然就拥有了比较和排序的能力。
ConcurrentLinkedQueue
ConcurrentLinkedQueue并没有直接继承BlockingQueue,而是实现的Queue接口,少了take和put这两个阻塞方法。ConcurrentLinkedQueue内部也是由单向链表的方式实现,它是线程安全的无界非阻塞队列,与BlockingQueue不同的是,ConcurrentLinkedQueue通过CAS方式实现线程安全。
ConcurrentLinkedQueue 使用 CAS 非阻塞算法 + 不停重试,来实现线程安全,适合用在不需要阻塞功能,且并发不是特别剧烈的场景。
参考: |
标签:JUC,队列,抛出,元素,阻塞,无界,线程 From: https://www.cnblogs.com/xfeiyun/p/17233341.html