Which concurrent Queue implementation should I use in Java?

David Hofmann picture David Hofmann · Aug 19, 2009 · Viewed 110.9k times · Source

From the JavaDocs:

  • A ConcurrentLinkedQueue is an appropriate choice when many threads will share access to a common collection. This queue does not permit null elements.
  • ArrayBlockingQueue is a classic "bounded buffer", in which a fixed-sized array holds elements inserted by producers and extracted by consumers. This class supports an optional fairness policy for ordering waiting producer and consumer threads
  • LinkedBlockingQueue typically have higher throughput than array-based queues but less predictable performance in most concurrent applications.

I have 2 scenarios, one requires the queue to support many producers (threads using it) with one consumer and the other is the other way around.

I do not understand which implementation to use. Can somebody explain what the differences are?

Also, what is the 'optional fairness policy' in the ArrayBlockingQueue?

Answer

Justin Rudd picture Justin Rudd · Aug 19, 2009

ConcurrentLinkedQueue means no locks are taken (i.e. no synchronized(this) or Lock.lock calls). It will use a CAS - Compare and Swap operation during modifications to see if the head/tail node is still the same as when it started. If so, the operation succeeds. If the head/tail node is different, it will spin around and try again.

LinkedBlockingQueue will take a lock before any modification. So your offer calls would block until they get the lock. You can use the offer overload that takes a TimeUnit to say you are only willing to wait X amount of time before abandoning the add (usually good for message type queues where the message is stale after X number of milliseconds).

Fairness means that the Lock implementation will keep the threads ordered. Meaning if Thread A enters and then Thread B enters, Thread A will get the lock first. With no fairness, it is undefined really what happens. It will most likely be the next thread that gets scheduled.

As for which one to use, it depends. I tend to use ConcurrentLinkedQueue because the time it takes my producers to get work to put onto the queue is diverse. I don't have a lot of producers producing at the exact same moment. But the consumer side is more complicated because poll won't go into a nice sleep state. You have to handle that yourself.