Browse DevX
Sign up for e-mail newsletters from DevX


Minding the Queue: Java 1.5 Adds a New Data Structure Interface  : Page 4

The release of Java 1.5 finally provides built-in support for one of the most fundamental data structures in programming—the queue. This article explores the new Queue interface that's been added to the java.util package, demonstrating how to use this new support to streamline your data handling.




Building the Right Environment to Support AI, Machine Learning and Deep Learning

DelayQueue—I Am/Am Not Half-baked
In some cases, objects that you place on a queue should be on that queue for a certain amount of time before they are ready to be dequeued. This is where you use the java.util.concurrent.DelayQueue class, which implements the BlockingQueue interface. The DelayQueue requires that queue objects be resident on the queue for a specified amount of time.

The real world example that I thought of to illustrate this (which might make you hungry) involves muffins. Well, Muffin objects (as we are talking Java—no coffee pun intended). Suppose you have a DelayQueue upon which you place Muffin objects. The Muffin object (shown below) must implement the java.util.concurrent.Delayed interface to be placed on a DelayQueue. The interface requires the Muffin object to implement the getDelay method (shown below). The getDelay method, in essence, states how much time is left for the object to be kept in the DelayQueue. When the number returned by this method becomes zero or less than zero, the object is ready (or in this example, baked) and allowed to be dequeued (shown in Listing 3).

The Muffin class also implements the compareTo(java.util.concurrent.Delayed) method. Since the Delayed interface extends from the java.lang.Comparable class, this binds you by contract to implement the bakeCompletion time of the Muffin object.

Since you don't really want to eat a Muffin that's not fully cooked, place the Muffin on the DelayQueue for the recommended cooking time. Listing 4, taken from the class DelayQueueUsageExample, shows the queuing and dequeuing of the Muffin objects from the DelayQueue.

As you can see, the cooking time for a Muffin object is set using its constructor (the constructor expects the cooking time to be in seconds).

As stated before, the Muffin objects placed on the DelayQueue are not allowed to be dequeued until their delay time (a.k.a. cooking time) has expired. Elements are dequeued from the queue based on the oldest delay time. In this example, if you have a number of Muffin objects that have been cooked, they will be dequeued on a basis of how long they've been waiting to be dequeued (in other words, the oldest cooked Muffins get the dequeued before the newest cooked Muffins).

Catch 22—The SynchronousQueue
Another blocking queue implementation Java 1.5 makes available is the SynchronousQueue. Interestingly enough, this queue doesn’t have an internal capacity. This is intentional, as the queue is meant for handoff purposes. This means that in a synchronous queue setup, a put request must wait for a take request to the SynchronousQueue from another thread. At the same time, a take request must wait for a put request to the SynchronousQueue from another thread. To demonstrate the concept programmatically, take a look at the sample code. Similar to the LinkedBlockingQueue example earlier, it contains a consumer (SynchConsumer), which is shown in Listing 5.

The code in Listing 5 uses the poll (long timeout, TimeUnit unit) method of the SynchronousQueue class. This method allows for the polling process to wait for a specified amount of time (in this case 20 seconds) before getting tired of waiting for another thread to write to the SynchronousQueue for consumption.

The producer (SynchProducer) shown in Listing 6 uses a similar offer(E o, long timeout, TimeUnit unit) method to enqueue objects on the SynchronousQueue. Use of this method allows a wait time (in this case, 10 seconds) before getting tired of waiting for another thread to read from the SynchronousQueue.

TestSynchQueue shows the producer and consumer in action:

import java.util.concurrent.SynchronousQueue; import java.util.concurrent.LinkedBlockingQueue; public class TestSynchQueue { public static void main(String args[]) { SynchronousQueue<String> synchQueue = new SynchronousQueue<String>(); SynchProducer producer = new SynchProducer("ProducerA",synchQueue, System.out); SynchConsumer consumerA = new SynchConsumer("ConsumerA", synchQueue, System.out); consumerA.start(); producer.start(); } }

When trying to understand the concept behind a SynchronousQueue, keep in mind where these types of queues are commonly used. The JavaDoc for the Synchronous queue points out:

"They [synchronous queues] are well suited for handoff designs, in which an object running in one thread must sync up with an object running in another thread in order to hand it some information, event, or task."

Kulvir Singh Bhogal works as an IBM consultant, devising and implementing J2EE-centric solutions at customer sites across the nation.
Comment and Contribute






(Maximum characters: 1200). You have 1200 characters left.



Thanks for your registration, follow us on our social networks to keep up-to-date