阻塞队列
队列:先进先出的数据结构(FIFO)
java中的队列接口在java.util包下
常见的对列实现类有LinkedList
常见的阻塞队列:LinkedBlockingDeque,可以设置固定的容量,当队列有数据的时候会通知消费者消费,当对应满的时候会让生产者等待。
用LinkedBlockingDeque实现生产者消费者模式:两个厨师做烧饼,两个顾客买烧饼
@Test public void test15() { final int count = 5; LinkedBlockingDeque<String> shaobingQueue = new LinkedBlockingDeque<>(3); // List<String> xiaoBaiMsg = new LinkedList<>(); List<String> chushi1Msg = new LinkedList<>(); List<String> chushi2Msg = new LinkedList<>(); List<String> roadPeopleAmsg = new LinkedList<>(); List<String> roadPeopleBmsg = new LinkedList<>(); Thread roadPeopleA = new Thread(() -> { for (int i = 0; i < count; i++) { String take = null; try { take = shaobingQueue.take();//队列没数据的时候会通知线程等待 } catch (InterruptedException e) { e.printStackTrace(); } roadPeopleAmsg.add(String.format("%d 路人甲买到了 [%s]", System.currentTimeMillis(), take)); } }); Thread roadPeopleB = new Thread(() -> { for (int i = 0; i < count; i++) { String take = null; try { take = shaobingQueue.take(); } catch (InterruptedException e) { e.printStackTrace(); } roadPeopleBmsg.add(String.format("%d 路人乙买到了 [%s]", System.currentTimeMillis(), take)); } }); Thread chushi1 = new Thread(() -> { for (int i = 0; i < count; i++) { String format = String.format("第%d个烧饼", i + 1); try { shaobingQueue.put(format);//当队列满的时候会让线程等待 } catch (InterruptedException e) { e.printStackTrace(); } chushi1Msg.add(String.format("%d chushi1制作了 [%s],当前烧饼数量:%d", System.currentTimeMillis(), format, shaobingQueue.size())); } }); Thread chushi2 = new Thread(() -> { for (int i = 0; i < count; i++) { String format = String.format("第%d个烧饼", i + 1); try { shaobingQueue.put(format); } catch (InterruptedException e) { e.printStackTrace(); } chushi2Msg.add(String.format("%d chushi2制作了 [%s],当前烧饼数量:%d", System.currentTimeMillis(), format, shaobingQueue.size())); } }); chushi1.start(); chushi2.start(); roadPeopleA.start(); roadPeopleB.start(); try { chushi1.join(); chushi2.join(); roadPeopleA.join(); roadPeopleB.join(); } catch (InterruptedException e) { SmallTool.printTimeAndThread("join 产生中断 "+ e.getMessage()); } System.out.println(chushi1Msg.stream().collect(Collectors.joining("\n"))); System.out.println(chushi2Msg.stream().collect(Collectors.joining("\n"))); System.out.println("--------"); System.out.println(roadPeopleAmsg.stream().collect(Collectors.joining("\n"))); System.out.println(roadPeopleBmsg.stream().collect(Collectors.joining("\n"))); }
阻塞队列常用的6个方法:
//存放: put(E) ------ 一直等待 offer(E, long, TimeUnit) ------- 等待一定时间,返回boolean offer(E) ----------- 不等待,返回boolean //获取: take() --------- 一直等待 poll(long, TimeUnit) ------ 等待一定时间,没有返回null poll() ---------- 不等待,没有返回null
常用的阻塞队列:
1、ArrayBlockingQueue:由数组实现的有界队列,需要指定队列的长度,同时我们也可以设置队列是都是公平的,当我们设置了容量后就不能再修改了,符合数组的特性,此队列按照先进先出(FIFO
)的原则对元素进行排序,公平指的是消费线程先到的先消费
public ArrayBlockingQueue(int capacity) {...} public ArrayBlockingQueue(int capacity, boolean fair) {...}
2、LinkedBlockingQueue:由链表实现的队列,这个队列的长度是 Integer.MAX_VALUE,可以设置队列长度
3、SynchronousQueue:是一个不存储任何元素的阻塞队列,每一个put
操作必须等待take
操作,否则不能添加元素。同时它也支持公平锁和非公平锁,synchronousQueue
的容量并不是1,而是0。因为它本身不会持有任何元素,它是直接传递的,synchronousQueue
会把元素从生产者直接传递给消费者,在这个过程中能够是不需要存储的
public SynchronousQueue() { this(false); } public SynchronousQueue(boolean fair) { transferer = fair ? new TransferQueue<E>() : new TransferStack<E>(); }
4、PriorityBlockingQueue:是一个支持优先级排序的无界阻塞队列,可以通过自定义实现 compareTo()
方法来指定元素的排序规则,或者通过构造器参数 Comparator
来指定排序规则。但是需要注意插入队列的对象必须是可比较大小的,也就是 Comparable
的,否则会抛出 ClassCastException
异常
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 震惊!C++程序真的从main开始吗?99%的程序员都答错了
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
· 单元测试从入门到精通
· winform 绘制太阳,地球,月球 运作规律
· 上周热点回顾(3.3-3.9)