What is LinkedBlockingQueue ? How to use LinkedBlockingQueue ?

The LinkedBlockingQueue class implements the BlockingQueue interface. Read the BlockingQueue for more information about the interface. The LinkedBlockingQueue is an optionally-bounded blocking queue based on linked nodes. This queue orders elements FIFO (first-in-first-out). The head of the queue is the element that has been on the queue for the longest period of time. The tail of the queue is the element that has been on the queue for the shortest period of time. New elements are inserted at the tail of the queue, and the queue retrieval operations obtain elements at the head of the queue. Linked queues typically have higher throughput than array-based queues but less predictable performance in most concurrent applications.

There are 3 ways to create a LinkedBlockingQueue :

// Creates a LinkedBlockingQueue with a capacity of Integer.MAX_VALUE.
LinkedBlockingQueue();
// Creates a LinkedBlockingQueue with a capacity of Integer.MAX_VALUE,
// initially containing the elements of the given collection,
// added in traversal order of the collection's iterator.
LinkedBlockingQueue(Collection c);
// Creates a LinkedBlockingQueue with the given (fixed) capacity.
LinkedBlockingQueue(int capacity);

The LinkedBlockingQueue keeps the elements internally in a linked structure (linked nodes). This linked structure can optionally have an upper bound if desired. If no upper bound is specified, Integer.MAX_VALUE is used as the upper bound. Linked nodes are dynamically created upon each insertion unless this would bring the queue above capacity. This class and its iterator implement all of the optional methods of the Collection and Iterator interfaces.

Following are some important methods and their behaviour for a LinkedBlockingQueue :

a. offer(E e) : It inserts the element at the tail of queue without exceeding LinkedBlockingQueue size. On success it returns true otherwise false.b. put(E e) : Inserts the element at the tail of the queue and waits for space if necessary.c. peek() : It retrieves the head of the queue without deleting it and returns null if empty.d. poll() : It retrieves and removes the head of the queue and returns null if empty.e. remove(Object o) : Removes the specified element from the queue.f. take() : Retrieves and removes the head of the queue and waits if necessary.

Here is how to instantiate and use a LinkedBlockingQueue

Like in our previous example about ArrayBlockingQueue, we are going to use a Producer-Consumer model in order to check the functionality of our LinkedBlockingQueue. Here in this example we have a TicketProducer that produces 10 tickets in a LinkedBlockingQueue. And we have 2 consumer classes as TicketConsumer which consumes tickets from the queue and a TicketWatcher consumer that watches the current status of the Queue.

As you can see, by running 3 threads simultaneously, we took advantage of the concurrency capabilities of LinkedBlockingQueue completely. The only thing that we had to do is keep it track whether or not the Producer thread was still running, and the rest of the implementation was thread-safe by default. By checking the output you can clearly see the effect of every thread, and the final result.