一个容量有限的
BlockingQueue
也可以帮助你控制某种类型请求的速度。使用无界队列,生产者可能会远远领先于消费者。任务最终会被执行(除非它们导致
OutOfMemoryError
),但是生产者可能已经放弃很久了,所以努力是浪费的。
在这种情况下,更好的方法是向潜在的生产者发出队列已满的信号,并快速失败。例如,生产者可能是一个Web请求,用户不想等待太长时间,即使在等待时它不会消耗太多CPU周期,但它正在使用像套接字和一些内存这样的有限资源。放弃将使已排队的任务更有机会及时完成。
关于修改后的问题,我的理解是:“在池中存储对象的好的集合是什么?”
对于许多池而言,一个无边界的LinkedBlockingQueue
是一个不错的选择。然而,根据您的池管理策略,ConcurrentLinkedQueue
也可能适用。
在池应用程序中,阻塞“put”是不合适的。控制队列的最大大小是池管理器的工作——它决定何时为池创建或销毁资源。池的客户端从池中借用和返回资源。添加新对象或将以前借用的对象返回到池中应该是快速、非阻塞的操作。因此,有界容量队列不适用于池。
另一方面,当从池中检索对象时,大多数应用程序希望等待资源可用。阻塞式的“取”操作至少是暂时有效的,比“忙等待”——重复轮询直到资源可用——更加高效。在这种情况下,
LinkedBlockingQueue
是一个不错的选择。借用者可以无限期地使用
take
阻塞,或使用
poll
限制它愿意阻塞的时间。
较少见的情况是客户端根本不愿阻塞,但如果池为空,则有能力为自己创建资源。在这种情况下,
ConcurrentLinkedQueue
是一个不错的选择。这是一种灰色地带,希望尽可能共享资源(例如内存),但速度更加重要。在最坏的情况下,这会退化为每个线程都有自己的资源实例;那么与其费心试图在线程之间共享,不如不共享更有效率。
这些集合在并发应用程序中提供了良好的性能和易用性。对于非并发应用程序,
ArrayList
很难被击败。即使对于动态增长的集合,
LinkedList
的每个元素开销也允许带有一些空槽的
ArrayList
在内存方面保持竞争力。