应用场景
阻塞队列这个知识点,之前了解过,但没有深入。其实阻塞队列应用场景还是很多的,比如线程池用阻塞队列存放任务,然后处理任务。生产者消费者模式。总之阻塞队列我觉得还是很有必要深入了解的。
常用队列详细介绍
(1)ArrayBlockingQueue
该阻塞队列,底层是基于数组实现的有界阻塞队列,是BlockingQueue的实现类。默认下是非公平锁。使用ReentrantLock来保证线程安全。 但是内部方法这里使用的是一个lock对象,也就是说,当调用添加方法(put,offer,add)和获取方法(take, poll)时,这两个方法并不能并发执行。
(2)LinkedBlockingQueue
底层是基于链表的无阻塞队列。也是BolckingQueue的实现类。和ArrayBlockingQueue底层一样 使用ReentrantLock来保证线程安全,不一样的是Linked BlockingQueue 使用的是分离锁,也就是写数据用的是一把锁,读数据的时候用的是另一把锁。所以性能非常的好,可以并发的执行读写。
(3)DelayQueue
延迟阻塞队列,在添加元素时设置,延迟时长。读取数据时只能对那些过了延迟时常的元素可见。
(4)SynchronousQueue
该队列有点特殊,队列不存储任何元素,每一次写操作就要有对应的读操作。如果当写入元素时,没有消费。那么写入线程将会一直阻塞,直到该消息被消费。简单来说,写入操作和读取操作是一对,绑定一起的。必须一起完成。 该队列是通过cas来保证线程安全的。和之前的队列不一样的就是,该队列不用锁住整个队列,性能提升。但是缺点就是不能存放元素。
(5)LinkedTransferQueue
该队列实现了TransferQueue接口,该接口对比之前主要扩展了两个功能,tryTransfer方法和transfer方法。
transfer方法就和使用SynchronousQueue的一样的。当生产者生产消息时,此时如果没有消费者等待消费,那么将会一直阻塞,直到消费者消费该消息。
tryTransfer方法 和transfer的区别就是,当没消费者等待消费时会立即返回,不会进行阻塞。
tryTransfer可以设置时间,代表阻塞等待时间,如果超过该时间,消息没有被消费,那么就返回false,如果在设置时间内消费了,就返回true。
该队列也是使用cas来保证线程安全。可以说是SynchronousQueue和linkedBlockingQueue的结合,效率高的同时也能存储元素。
阻塞队列方法
生产:add,put,offer
add:不会阻塞,添加成功时返回true,不响应中断,当队列已满导致添加失败时抛出IllegalStateException。
offer:不会阻塞,添加成功时返回true,因队列已满导致添加失败时返回false,不响应中断。
put:会阻塞会响应中断。
消费:take,poll
take:会响应中断,会一直阻塞直到取得元素或当前线程中断。
poll:会响应中断,会阻塞,阻塞时间参照方法里参数timeout.timeUnit,当阻塞时间到了还没取得元素会返回null