JUC:阻塞队列
第一组api(add,remove,element)
add(E) 在尾部添加元素,如果队列满了,抛出IllegalStateException: Queue full异常
remove() 删除队列的头元素,如果队列为空,抛出 NoSuchElementException 异常
element() 查看队列的头元素,如果队列为空,抛出 NoSuchElementException 异常(底层调用的是peek())
blockingQueue.add("a"); blockingQueue.add("b"); blockingQueue.add("c"); // 超过容量会抛异常 java.lang.IllegalStateException: Queue full // blockingQueue.add("d"); System.out.println(blockingQueue.remove()); System.out.println(blockingQueue.remove()); System.out.println(blockingQueue.remove()); // 空队列继续取元素 抛出没有元素异常 java.util.NoSuchElementException // System.out.println(blockingQueue.remove()); // element() 查看队列的头元素,但不删除(空队列会抛出NoSuchElementException) System.out.println(blockingQueue.element());
第二组api(offer,poll,peek)
offer(E) 在尾部添加元素,队列已满,返回false
poll() 从头部弹出一个元素,空队列返回null
peek() 查看队列的头元素,空队列返回null
System.out.println(blockingQueue.offer("a")); System.out.println(blockingQueue.offer("b")); System.out.println(blockingQueue.offer("c")); // System.out.println(blockingQueue.offer(null)); // NullPointerException System.out.println(blockingQueue.offer("d")); // 队列已满,不抛异常,返回值为 false System.out.println(blockingQueue.poll()); System.out.println(blockingQueue.poll()); System.out.println(blockingQueue.poll()); System.out.println(blockingQueue.poll()); // 空队列,继续弹出元素 无异常,返回值为 null System.out.println(blockingQueue.peek()); // 获取队列的头元素,空队列返回 null
第三组api(offer(E,time,TimeUnit),poll(time,timeUnit))
offer("a", 2, TimeUnit.SECONDS) 队列已满,等待2秒,时间过了直接放弃插入
poll(2, TimeUnit.SECONDS) 队列已空,等待两秒,如果还未空,直接返回null
try { System.out.println(blockingQueue.offer("a", 2, TimeUnit.SECONDS)); System.out.println(blockingQueue.offer("b", 2, TimeUnit.SECONDS)); System.out.println(blockingQueue.offer("c", 2, TimeUnit.SECONDS)); // 队列已满,等待2秒种,仍未加入队列,放弃添加并返回false System.out.println(blockingQueue.offer("d", 2, TimeUnit.SECONDS)); System.out.println(blockingQueue.poll(2, TimeUnit.SECONDS)); System.out.println(blockingQueue.poll(2, TimeUnit.SECONDS)); System.out.println(blockingQueue.poll(2, TimeUnit.SECONDS)); // 队列已空,等待两秒,仍然为空,放弃取出元素,返回null System.out.println(blockingQueue.poll(2, TimeUnit.SECONDS)); } catch (InterruptedException e) { e.printStackTrace(); }
第四组api(put(),take() )
put() 如果队列已满,会一直阻塞,直到队列有空位置,再插入队列
take() 如果队列已空,会一直阻塞,直到队列有新元素,再取出元素
try { blockingQueue.put("a"); blockingQueue.put("b"); blockingQueue.put("c"); // 如果队列已满,会一直阻塞,直到队列有空位置,再插入队列 blockingQueue.put("d"); System.out.println(blockingQueue.take()); System.out.println(blockingQueue.take()); System.out.println(blockingQueue.take()); // 如果队列已空,会一直阻塞,直到队列有新元素,取出元素 System.out.println(blockingQueue.take()); } catch (InterruptedException e) { e.printStackTrace(); }
同步队列: SynchronousQueue
每一个put操作,就需要有一个 take操作!
1 BlockingQueue<String> blockingQueue = new SynchronousQueue<>(); 2 // A 存 3 new Thread(() -> { 4 try { 5 System.out.println(Thread.currentThread().getName() + " put a"); 6 blockingQueue.put("a"); 7 System.out.println(Thread.currentThread().getName() + " put b"); 8 blockingQueue.put("b"); 9 System.out.println(Thread.currentThread().getName() + " put c"); 10 blockingQueue.put("c"); 11 } catch (InterruptedException e) { 12 e.printStackTrace(); 13 } 14 }, "A").start(); 15 16 // B 取 17 new Thread(() -> { 18 try { 19 TimeUnit.SECONDS.sleep(2); 20 System.out.println(Thread.currentThread().getName() + " get "+ blockingQueue.take()); 21 22 TimeUnit.SECONDS.sleep(2); 23 System.out.println(Thread.currentThread().getName() + " get "+ blockingQueue.take()); 24 25 TimeUnit.SECONDS.sleep(2); 26 System.out.println(Thread.currentThread().getName() + " get "+ blockingQueue.take()); 27 } catch (InterruptedException e) { 28 e.printStackTrace(); 29 } 30 }, "B").start();
结果: