Section 14.1. Using the Methods of Queue


14.1. Using the Methods of Queue

Let's look at examples of the use of these methods. Queues should provide a good way of implementing a task manager, since their main purpose is to yield up elements, such as tasks, for processing. For the moment we shall use ArrayDeque as the fastest and most straightforward implementation of Queue (and also of Deque, of course). But, as before, we shall confine ourselves to the methods of the interfacethough you should note that, in choosing a queue implementation, you are also choosing an ordering. With ArrayDeque, you get FIFO orderingwell, our attempts to get organized using fancy scheduling methods never seem to work very well; perhaps it's time to try something simpler.

ArrayDeque is unbounded, so we could use either add or offer to set up the queue with new tasks.

 Queue<Task> taskQueue = new ArrayDeque<Task>(); taskQueue.offer(mikePhone); taskQueue.offer(paulPhone); 

Any time we feel ready to do a task, we can take the one that has reached the head of the queue:

 Task nextTask = taskQueue.poll(); if (nextTask != null) {   // process nextTask } 

The choice between using poll and remove depends on whether we want to regard queue emptiness as an exceptional condition. Realisticallygiven the nature of the applicationthat might be a sensible assumption, so this is an alternative:

 try {   Task nextTask = taskQueue.remove();   // process nextTask } catch (NoSuchElementException e) {   // but we *never* run out of tasks! } 

This scheme needs some refinement to allow for the nature of different kinds of tasks. Phone tasks fit into relatively short time slots, whereas we don't like to start coding unless there is reasonably substantial time to get into the task. So if time is limitedsay, until the next meetingwe might like to check that the next task is of the right kind before we take it off the queue:

 Task nextTask = taskQueue.peek(); if (nextTask instanceof PhoneTask) {   taskQueue.remove();   // process nextTask } 

These inspection and removal methods are a major benefit of the Queue interface; Collection has nothing like them (though NavigableSet now does). The price we pay for this benefit is that the methods of Queue are useful to us only if the head element is actually one that we want. True, the class PriorityQueue allows us to provide a comparator that will order the queue elements so that the one we want is at the head, but that may not be a particularly good way of expressing the algorithm for choosing the next task (for example, if you need to know something about all the outstanding tasks before you can choose the next one). So in this situation, if our to-do manager is entirely queue-based, we may end up going for coffee until the meeting starts. As an alternative, we could consider using the List interface, which provides more flexible means of accessing its elements but has the drawback that its implementations provide much less support for multi-thread use.

This may sound too pessimistic; after all, Queue is a subinterface of Collection, so it inherits methods that support traversal, like iterator. In fact, although these methods are implemented, their use is not recommended in normal situations. In the design of the queue classes, efficiency in traversal has been traded against fast implementation of the methods of Queue; in addition, queue iterators do not guarantee to return their elements in proper sequence and, for some concurrent queues, will actually fail in normal conditions (see Section 14.3.2).

In the next section we shall look at the direct implementations of QueuePriorityQueue and ConcurrentLinkedListand, in Section 14.3, at BlockingQueue and its implementations. The classes in these two sections differ widely in their behavior. Most of them are thread-safe; most provide blocking facilities (that is, operations that wait for conditions to be right for them to execute); some support priority ordering; oneDelayQueueholds elements until their delay has expired, and anotherSynchronousQueueis purely a synchronization facility. In choosing between Queue implementations, you would be influenced more by these functional differences than by their performances.




Java Generics and Collections
Java Generics and Collections
ISBN: 0596527756
EAN: 2147483647
Year: 2006
Pages: 136

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net