I'm reading this:
In which Doug Lea says:
Usually, when you are putting something into a queue, you will have just allocated that new something. And similarly, when you take something out you usually use it and then let it become garbage. In which case the extra allocation for a queue node is not going to make much difference in overall GC, so you might as well go for the better scalability of LinkedBlockingQueue. I think this is the most common use case.
But, if you aren't allocating the things put into queues, and don't expect lots of threads to be contending when the queue is neither empty nor full, then ArrayBlockingQueue is likely to work better.
I want to know what does Aren't allocating the things put into queues
mean?
Also, this sentence: don't expect lots of threads to be contending when the queue is neither empty nor full, then ArrayBlockingQueue is likely to work better
, can someone explain that a little bit more specifically?
CodePudding user response:
To me that seems to mean following:
-
I want to know what does
Aren't allocating the things put into queues
mean?This is about the GC overhead which they discus.
LinkedBlockingQueue
creates new internalNode
object for every added item, which means it generates garbage and, as a result, causes garbage collection (GC).
Doug says that often the items we store in a queue are objects which:- are created right before they are added to the queue
- become unused (and eligible for GC) shortly after they are removed from the queue
In these cases the items themselves cause GC anyway, therefore it's not a problem that
Node
objects require GC as well.But if you only store long-lived objects in a queue, then
LinkedBlockingQueue
might become the only thing that causes GC.
Then you might want to useArrayBlockingQueue
instead to avoid GC.
(ArrayBlockingQueue
doesn't create any objects when items added/removed) -
Also, this sentence:
don't expect lots of threads to be contending when the queue is neither empty nor full, then ArrayBlockingQueue is likely to work better
, can someone explain that a little bit more specifically?LinkedBlockingQueue
uses two locks: one forput()
and one fortake()
.
ArrayBlockingQueue
uses one lock for bothput()
andtake()
.
As a result when "the queue is neither empty nor full
" (i.e. when neitherput()
nortake()
have to wait) and there are two threads: one executesput()
, another one executestake()
- if the queue is
LinkedBlockingQueue
, then the threads don't block each other - if the queue is
ArrayBlockingQueue
, then one thread will have to wait until the other one is done
- if the queue is