nbsp; //阻塞直到被获取
queue.transfer(1);
//生产者放入的1被取走了
System.out.println(Thread.currentThread().getName()+"放入的1被取走了");
} catch (InterruptedException e) {
e.printStackTrace();
}
},"生产者").start();
?
TimeUnit.SECONDS.sleep(3);
//main取出队列中的元素
System.out.println(Thread.currentThread().getName()+"取出队列中的元素");
queue.poll();
}
tryTransfer()
无论消费者是否消费都直接返回
@Test
public void testTryTransfer() throws InterruptedException {
LinkedTransferQueue<Integer> queue = new LinkedTransferQueue<>();
//false
System.out.println(queue.tryTransfer(1));
//null
System.out.println(queue.poll());
?
new Thread(()->{
try {
//消费者取出2
System.out.println(Thread.currentThread().getName()+"取出"+queue.poll(2, TimeUnit.SECONDS));
} catch (InterruptedException e) {
e.printStackTrace();
}
},"消费者").start();
TimeUnit.SECONDS.sleep(1);
//true
System.out.println(queue.tryTransfer(2));
}
tryTransfer(long,TimeUnit)
在超时时间内消费者消费元素返回true,反之返回false
总结
ArrayBlockingQueue由环形数组实现,固定容量无法扩容,使用非公平的可重入锁锁、两个等待队列操作入队、出队操作,适合并发小的场景
LinkedBlockingQueue由单向链表实现,默认无界,使用两个可重入锁、两个等待队列进行入队、出队操作,并在此期间可能唤醒生产者或消费者线程,以此提高并发性能
LinkedBlockingDeque由双向链表实现,在LinkedBlockingQueue的基础上,能够在队头、队尾都进行添加、删除操作,适用工作窃取算法1
PriorityBlockingQueue由堆排序实现的优先级队列,具体排序算法由Comparable、Comparator来实现,适用于需要根据优先级排序处理任务的场景
DelayQueue 是一个延时队列,队列中存储的元素需要实现Delayed
接口来获取延时时间,适用于缓存失效、定时任务的场景
SynchronousQueue不存储元素,只将生产者生产的元素传递给消费者, 适用于传递性的场景,比如不同线程间传递数据
LinkedTransgerQueue是传输形的阻塞队列,适用于单个元素传递的场景
在使用无界的阻塞队列时,需要设置容量,避免存储任务太多导致OOM
最后(不要白嫖,一键三连求求拉~)
本篇文章被收入专栏 由点到线,由线到面,深入浅出构建Java并发编程知识体系,感兴趣的同学可以持续关注喔
本篇文章笔记以及案例被收入 gitee-StudyJava、 github-StudyJava 感兴趣的同学可以stat下持续关注喔~
案例地址:
Gitee-JavaConcurrentProgramming/src/main/java/E_BlockQueue
Github-JavaConcurrentProgramming/src/main/java/E_BlockQueue
有什么问题可以在评论区交流,如果觉得菜菜写的不错,可以点赞、关注、收藏支持一下~
关注菜菜,分享更多干货,公众号:菜菜的后端私房菜
本文由博客一文多发平台 OpenWrite 发布!