JUC并发编程学习笔记(九)阻塞队列

打印 上一主题 下一主题

主题 883|帖子 883|积分 2649

阻塞队列

阻塞
队列
队列的特性:FIFO(fist inpupt fist output)先进先出
不得不阻塞的情况




什么情况下会使用阻塞队列:多线程并发处理、线程池
学会使用队列
添加、移除
四组API
方式抛出异常不抛出异常,有返回值阻塞等待超时等待添加addofferputoffer(E e, long timeout, TimeUnit unit)移除removepolltakepoll(long timeout, TimeUnit unit)检测队首元素elementpeek1、抛出异常
  1. public static void test01(){
  2.     //队列是有大小的,创建时要明确该队列最大能有几个元素
  3.     BlockingQueue queue = new ArrayBlockingQueue<>(3);
  4.     //当你添加的元素超出队列规定的最大元素量时,抛出异常java.lang.IllegalStateException: Queue full
  5.     System.out.println(queue.add("A"));
  6.     System.out.println(queue.add("B"));
  7.     System.out.println(queue.add("C"));
  8.     //当你移除的元素超出队列中含有的元素量时,抛出异常java.util.NoSuchElementException
  9.     System.out.println(queue.element());
  10.     System.out.println(queue.remove());
  11.     System.out.println(queue.element());
  12.     System.out.println(queue.remove());
  13.     System.out.println(queue.element());
  14.     System.out.println(queue.remove());
  15.     System.out.println(queue.add("D"));
  16. }
复制代码
2、不抛出异常
  1. public static void test02(){
  2.     //队列是有大小的,创建时要明确该队列最大能有几个元素
  3.     BlockingQueue queue = new ArrayBlockingQueue<>(3);
  4.     //当你添加的元素超出队列规定的最大元素量时,不抛出异常,通过返回的boolean值为false来表明
  5.     System.out.println(queue.offer("A"));
  6.     System.out.println(queue.offer("B"));
  7.     System.out.println(queue.offer("C"));
  8.     //当你移除的元素超出队列中含有的元素量时,不抛出异常,返回null来提示队列已经没有元素可以弹出了
  9.     System.out.println(queue.peek());
  10.     System.out.println(queue.poll());
  11.     System.out.println(queue.peek());
  12.     System.out.println(queue.poll());
  13.     System.out.println(queue.peek());
  14.     System.out.println(queue.poll());
  15.     System.out.println(queue.offer("D"));
  16. }
复制代码
3、阻塞等待
  1.     public static void test03() throws InterruptedException {
  2.         //队列是有大小的,创建时要明确该队列最大能有几个元素
  3.         BlockingQueue queue = new ArrayBlockingQueue<>(3);
  4.         queue.put("a");
  5.         queue.put("b");
  6.         queue.put("c");
  7.         //当队列被元素占满后再进行添加,会一直阻塞等待,知道该元素加入队列
  8. //        queue.put("c");
  9.         System.out.println(queue.take());
  10.         System.out.println(queue.take());
  11.         System.out.println(queue.take());
  12.         //当队列中没有元素时还去取,也会一直阻塞等待
  13. //        System.out.println(queue.take());
  14.     }
复制代码
4、超时等待
  1. public static void test04() throws Exception{
  2.     //队列是有大小的,创建时要明确该队列最大能有几个元素
  3.     BlockingQueue queue = new ArrayBlockingQueue<>(3);
  4.     System.out.println(queue.offer("a"));
  5.     System.out.println(queue.offer("b"));
  6.     System.out.println(queue.offer("c"));
  7.     //当队列被占满时,设置超时等待,超过两秒就不等了,进不去就不进了
  8.     System.out.println(queue.offer("d", 2, TimeUnit.SECONDS));
  9.     System.out.println(queue.poll());
  10.     System.out.println(queue.poll());
  11.     System.out.println(queue.poll());
  12.     //当队列元素为空时,设置超时等待,超过两秒就不等了,拿不到就不拿了
  13.     System.out.println(queue.poll(2, TimeUnit.SECONDS));
  14. }
复制代码
SynchronousQueue
同步队列:同步队列每次插入操作都必须等待另一个线程执行相应的删除操作,反之亦然。同步队列没有容量,也就意味着只有当一个元素弹出后才能再进入一个元素,只能同时有一个元素。

存取:put、take
  1. package org.example.qu;
  2. import java.util.concurrent.SynchronousQueue;
  3. import java.util.concurrent.TimeUnit;
  4. public class SynchronousQueueDemo {
  5.     public static void main(String[] args) {
  6.         SynchronousQueue<String> synchroQueue = new SynchronousQueue<String>();
  7.         new Thread(() -> {
  8.             try {
  9.                 //直接在队列中存入三个元素
  10.                 System.out.println(Thread.currentThread().getName() + ": put 1");
  11.                 synchroQueue.put("1");
  12.                 System.out.println(Thread.currentThread().getName() + ": put 2");
  13.                 synchroQueue.put("2");
  14.                 System.out.println(Thread.currentThread().getName() + ": put 3");
  15.                 synchroQueue.put("3");
  16.             } catch (InterruptedException e) {
  17.                 throw new RuntimeException(e);
  18.             }
  19.         }, "T1").start();
  20.         new Thread(() -> {
  21.             try {
  22.                 //每次取之间延迟三秒
  23.                 TimeUnit.SECONDS.sleep(3);
  24.                 System.out.println(synchroQueue.take());
  25.                 TimeUnit.SECONDS.sleep(3);
  26.                 System.out.println(synchroQueue.take());
  27.                 TimeUnit.SECONDS.sleep(3);
  28.                 System.out.println(synchroQueue.take());
  29.             } catch (InterruptedException e) {
  30.                 throw new RuntimeException(e);
  31.             }
  32.         }, "T2").start();
  33.     }
  34. }
复制代码
我们通过结果发现,将要存入的元素会等待已经被存入的元素取出后才会存入,延迟三秒取出时,将要存入的元素也在等待三秒取出后再存入,这就是所谓的同步队列每次插入操作都必须等待另一个线程执行相应的删除操作,反之亦然。
同步队列和其它BlockingQueue不一样,他不存储元素,你put了一个值必须take取出,否则不能再put进去元素。

免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?立即注册

x
回复

使用道具 举报

0 个回复

倒序浏览

快速回复

您需要登录后才可以回帖 登录 or 立即注册

本版积分规则

用户国营

金牌会员
这个人很懒什么都没写!

标签云

快速回复 返回顶部 返回列表