Queue满时add()抛IllegalStateException,仅限有界队列(如ArrayBlockingQueue);无界队列(如LinkedList)不抛此异常;remove()/element()空时抛NoSuchElementException;offer()/poll()是生产环境推荐组合,失败返回false/null而非异常。

Queue满时调用add()会抛出IllegalStateException
当底层实现是固定容量的队列(比如ArrayBlockingQueue),add()在无法入队时直接失败,不给你商量余地。它设计初衷就是“要么成功,要么明确报错”,适合你希望快速暴露容量问题的场景。
常见错误现象:Exception in thread "main" java.lang.IllegalStateException: Queue full,但很多人没意识到这和队列类型强相关——LinkedList这种无界队列永远不会抛这个异常。
-
add()和remove()是Collection接口定义的方法,语义偏“强制操作” - 有界队列才可能触发该异常;无界队列(如
LinkedList、PriorityQueue)永远返回true - 如果业务逻辑依赖“失败即告警”,用
add()更直接;但若只是试探性插入,别用它
Queue空时调用remove()或element()会抛NoSuchElementException
这两个方法对标add(),走的是“必须返回有效值”的路线。remove()取并删头结点,element()只查不删——但只要队列为空,二者都立即炸。
典型踩坑:在循环里写while (!q.isEmpty()) { process(q.remove()); }看似安全,但如果多线程并发修改了isEmpty()和remove()之间的状态,仍可能触发异常。
立即学习“Java免费学习笔记(深入)”;
-
remove()和element()都不推荐用于不确定是否非空的场景 - 它们和
add()/offer()不是简单两两对应关系:add()对offer(),remove()对poll(),element()对peek() - 并发环境下,即使先判空,也不能完全避免异常——除非用线程安全实现(如
ConcurrentLinkedQueue)且接受null作为空信号
offer()和poll()才是生产环境该默认用的组合
它们统一返回boolean或null,把控制权交还给你:失败不抛异常,靠返回值分支处理。这是异步、高并发、容错系统里的标准姿势。
使用场景:消息队列投递、任务缓冲池、背压控制。比如用offer()尝试塞任务,失败就降级写日志或走旁路;用poll()取任务,返回null就休眠再试。
-
offer(E e)成功返回true,满时返回false(不抛异常) -
poll()有元素则返回并移除,空时返回null;peek()类似,但不移除 - 注意
null是合法返回值,所以队列里不能存null元素,否则poll()无法区分“空队列”和“存了个null” - 性能上,
offer()/poll()通常比add()/remove()略轻——少一次异常构造开销,尤其在高频失败路径下
不同Queue实现对“满/空”的定义其实不一致
别以为所有Queue的“满”都是指容量耗尽。PriorityQueue没有容量限制,add()永远不会满;而SynchronousQueue容量恒为0,“满”等于“已有线程在等取”,“空”等于“已有线程在等放”。
这意味着:同一套异常处理逻辑,换一个实现就可能失效。比如你在ArrayBlockingQueue里靠捕获IllegalStateException做重试,在SynchronousQueue里根本捕不到——它满时offer()直接返回false,add()则阻塞(除非指定超时)。
-
LinkedBlockingQueue可配置容量,未指定时按Integer.MAX_VALUE算,实际视为无界 -
DelayQueue、PriorityBlockingQueue均无界,“满”逻辑不存在 - 真正需要关注“满行为”的,只有显式声明容量的阻塞队列:
ArrayBlockingQueue、带容量的LinkedBlockingQueue、SynchronousQueue
SynchronousQueue的“满”,本质是同步交接点上的竞争,跟内存容量毫无关系。










