UITL.CONCURRENT Research (8) - Exceeding Map, Collection, List and Set Queue

xiaoxiao2021-03-06  34

Beyond Map, Collection, List and Set Queue

First, copyright description:

Part of this article is taken from John Zukowski "Tame Tiger: Concurrent Collection" (http://www-900.ibm.com/developerWorks/cn/java/j-tiger06164/index.shtml?ca=dwcn-newsletter-java)

Second, the content introduction: DOUG LEA originally prepared Util.concurrent package became JSR-166, and then became the Tiger version of the J2SE platform. This new library provides a set of utilities that are often needed in concurrent programs. If you are interested in optimizing multi-thread access to a collection, then you are looking for a place.

At the early stage of Java programming, a professor at Suny, the New York State University (Suny) in Oswego decided to create a simple library to help developers build applications that can better handle multithreading. This is not to say that you cannot be implemented in an existing library, but just like there is a standard network library, it is easier to handle multithreading yourself with a debugged, trusted library. With the help of an associated books of Addision-Wesley, this library becomes more and more popular. Finally, the author DOUG LEA decided to try to make it a standard part of the Java platform - JSR-166.

Third, introduce the Queue interface: java.util package provides a new basic interface for the collection: java.util.queue. Although it is sure to add java.util.list as a queue to the corresponding two-end, this new Queue interface provides more methods for supporting, deleting, and checking a collection, as follows:

Public Boolean Offer (Object Element) Public Object Remove () PUBLIC OBJECT Poll () Public Object Element () Public Object PEEK ()

The Queue interface is designed as a collection of a member of the object. As a basic Collection operation, Queue provides some new addition, deletion, check operations. The following is a list of methods and rules:

Operation Method Rules Add Offer (x) Try to add, successfully returns true, unsemplie returning false add (x) Uncommon to throw an exception Delete Poll () Try to delete, successfully returns true remove () Unsuccessful Export an exception check peek () Try returns a member of the Queue header if queue is null, then return null element () returns a member of the Queue header if Queue is NULL, then throw an exception

Fourth, Queue works:

Queue's member sort: Queue is usually arranged in a FIFO manner, but it is not required. For example, priority queues are an exception queue, which arrays a queue member according to the comparator; there is also the order of the queue members; LIFO queue (the first out of the queue) is arranged in the order of advancement Queue member. Regardless of which arrangement is used, members of the queue head can be deleted using the remove () or poll () method. In the FIFO queue, new members are added to the tail of the queue. Other kinds of queues cannot use different storage methods. Each Queue implementation must provide its own arrangement properties.

Adder method Add a member if it returns true; if the failed returns false. This is different from the Collection.Add method in: Collection.Add will throw unchecked anomalies. Therefore, the Offer method is designed to be normal, not an abnormality, such as a fixed length. Remove () and poll () methods delete members of the column header. As for which member is deleted, it is completely in accordance with the queue's sorting rules, which is different in accordance with the implementation. The behavior of the REMOVE () and Poll () methods can only be different in the queue: the poll () method returns NULL, and the remove () method will throw an exception.

Element () and peek () methods only return to members of the quotation head without deleting any members.

The Queue interface does not define the method of blocking queue, and this method is usually used in concurrent programming. The method of blocking queues will allow members to wait to know space in the queue, which is defined in the edu.emory.mathcs.backport.java.util.concurrent.blockingQueue interface (an interface extends the Queue interface) J.

The implementation of the QUEUE interface is usually not allowed to insert a NULL member into the queue, although some implementation of LinkedList does not limit the insertion null. Even in some implementations that allow inserted queue interface, NULL does not allow insertion into QUQEUE, and the poll () method returns NULL when the queue does not contain any member.

The implementation of the QUEUE interface is usually not defined as a member-based Equals and HashCode method, but inherits some methods of identifying classes from the Object class. Because member-based Equals is not well defined because in different sort queues.

Using the basic queue in TiGer has two groups of queue implementations: the new BlockingQueue interface is implemented and the interface is not implemented. I will first analyze those who are not implemented.

In the simplest case, the original Java.util.LINKEDLIST implementation has been transformed into a Java.util.List interface, but also implements a java.util.Queue interface. A collection can be regarded as any of the two. Listing 1 Display a way to use LinkedList as Queue:

Listing 1. Using Queue Realization

Queue Queue = new LinkedList (); queue.offer ("one"); Queue.offer ("two"); Queue.offer ("three"); Queue.offer ("four"); //Head of queue should Be one system.out.println ("Head of queue is:" queue.poll ());

More complicated is a new Java.util.AbstractRactQueue class. This type of work is similar to the Java.util.AbstractList and Java.util.AbstractSet class. When you create a custom set, you don't need to implement the entire interface, just inherit the abstraction implementation and fill in the details. When using AbstractQueue, it must be implemented for method Offer (), POLL (), and peek (). Methods such as add () and addall () are modified to use offer (), while Clear () and remove () use Poll (). Finally, Element () uses peek (). Of course, you can provide optimization implementation of these methods in subclasses, but don't do this. Moreover, you don't have to create your own subclasses, you can use several built-in implementations, two of which do not block queues: priorityQueue, and ConcurrentLinkedQueue. The PriorityQueue and the ConcurrentlinkedQueue class are added to the Collection Framework to implement two specific collection implementations. The PriorityQueue class essentially maintains a sequence list. The elements added to Queue are positioned according to their natural sorting (implemented by their java.util.comParable) or by the Java.util.comParator implementation of the constructor. Change the LinkedList in Listing 2 to PriorityQueue will print out of ONE, because the natural order of the alphabetic-string - Four is the first. ConcurrentlinkedQueue is a link-based queue based on link nodes. Concurrent access does not need to synchronize. Because it adds an element to the tail of the queue and deletes them from the head, as long as it does not need to know the size of the queue, ConcURRENTLINKEDQUEUE can work very well. Collecting information about the size of the queue will be slow and need to traverse queues.

Use the blocked queue new java.util.concurrent package to join the BlockingQueue interface and five block queues in the specific set class available in Collection Framework. If you don't get familiar with the blockage concept, it is essentially a FIFO data structure with a distortion. Not immediately adding or deleting elements from the queue, thread performs operational operation, until space or elements are available. The javadoc of the BlockingQueue interface gives the basic usage of blocking queues, as shown in Listing 2. The PUT () operation in the producer will block without space, while the consumer's Take () operation will block when there is no thing in the queue.

Listing 2. Using BlockingQueue

class Producer implements Runnable {private final BlockingQueue queue; Producer (BlockingQueue q) {queue = q;} public void run () {try {while (true) {queue.put (produce ());}} catch (InterruptedException ex) {... Handle ...}} Object Produce () {...}} Class Consumer IMPLEments Runnable {Private Final BlockingQueueue Queue ;:} {queue = q;} public void Run () {Try {while (True) {consume (queue.take ());}} catch (interruptexception ex) {... handle ...}} void consume (object x) {...}} class setup {void main () { BlockingQueue = new somequeueImplement (); product P = New Productation (Q); Consumer C1 = New Consumer (Q); Consumer C2 = New Consumer (Q); New Thread (p) .Start (); New Thread (C1) .Start (); New thread (C2) .Start ();}} The five queues are provided with different:

ArrayBlockingQueue: A bounded queue supported by arrays. LinkedBlockingQueue: An optional bound query supported by the link node. PriorityBlockingQueue: A unreasonable priority queue supported by priority stacks. DELAYQUEUE: A time-based dispatch queue supported by priority. SynchronousQueue: A simple aggregation mechanism using the BlockingQueue interface.

The first two class ArrayBlockingQueue and LinkedBlockingQueue are almost the same, but they are different in the backup memory. LinkedBlockingQueue does not always have capacity boundaries. LINKEDBLOCKINGQUEUE classes without size boundary never wait for an interpolation queue (at least before it has Integer.max_Value elements).

PriorityBlockingQueue is a queue with unbreranged capacity, which uses the Comparable order sequencing order of the elements to logically sequentially maintained elements. It can be seen as a possibility for Treeset. For example, adding strings in the queue ONE, TWO, Three, and FOUR will result in FOUR to be taken out. For elements without natural sequence, a Compare can be provided for the constructor. But there is a trick to PriorityBlockingQueue. The Iterator instance returned from iTerator () does not need to return elements in priority order. If you must traverse all elements in priority order, let them sort them by the toarray () method, like arrays.sort (pq.toArray ()).

The new DELAYQUEUE implementation may be one of the most interesting (and most complex). Elements joining into the queue must implement a new Delayed interface (only one method - long getdelay (java.util.concurrent.timeUnit unit)). Because the queue size has no boundary, the addition can be returned immediately, but the elements cannot be removed from the queue before the delay time has passed. If multiple elements have completed delay, the earliest failure / failed time is the first to take the first. I actually didn't listen to this complicated. Listing 3 demonstrates the use of this new block queue collection:

Listing 3. Using DELAYQUEUE

import edu.emory.mathcs.backport .. *; import edu.emory.mathcs.backport..concurrent *;. public class Delay {/ ** * Delayed implementation that actually delays * / static class NanoDelay implements Delayed {long trigger; NanodeLay (long i) {trigger = utils.nanotime () i;} public int compareto (Object Y) {long i = trigger; long j = (nanodelay) y) .trigger; if (i j) Return 1; return 0;} public boolean equals (Object Other) {return (nanodelay)} .trigger == Trigger;} public boolean equals (nanodelay Other) {Return (Nanodelay) other) .trigger == trigger;} public long getDelay (TimeUnit unit) {long n = trigger - Utils.nanoTime (); return TimeUnit.NANOSECONDS.convert (n, unit);} public long getTriggerTime () {return trigger; PUBLIC STRING TOSTRING () {Return String.Valueof (TRIGGER);}} public static void main Args []) throws interruptedException {random random = new random (); delayQueue queue = new delayQueue (); for (int i = 0; i <5; i ) {queue.add (new nanodelay (1000) ));} Long Last = 0; for (int I = 0; i <5; i ) {nanodelay delay = (nanodelay); long TT = delay.gettriggertime (); system.out. Println ("Trigger Time:" TT); if (i! = 0) {system.out.println ("Delta:" (tt - last));} Last = tt;}}}

This example is first is an internal class Nanodelay, which is substantially a number of nanoseconds, which utilizes the nanotime () method for edu.emory.mathcs.backport.java.util.utils. The main () method is then just putting the Nanodelay object in the queue and takes them again. If you want the queue item to do something else, you need to join the method in the implementation of the Delayed object, and call this new method after taking it from the queue. (Please extend Nanodelay to do some interesting things to add other methods.) Display the time difference between the two calls from the queue. If the time difference is a negative number, it can be considered an error, because it will never be taken from the queue from the queue after the delay time is over. The SynchronousQueue class is the easiest. It has no internal capacity. It is like a hand hand mechanism between threads. Add an element in the queue to wait for another thread consumers. When this consumers appear, this element is directly transmitted between consumers and producers, never add to the blocking queue.

Listing 4: Using DelayQueue to achieve producer / consumer

Package bjinfotech.util.ThreadManage.concurrent.ThreadManage.Concurrent.Tryit; / * * delayQueue_test.java * * Created on January 11, 2005, 4:23 pm, * / Import edu.emory.mathcs.Backport.java.util.Concurrent. * Import java.util. *; / ** * Test Util.Concurrent package JSDK1.4 version - backport-util-concurrent --- DelayQueue * @author smart pig * / public class delayQueue_test {private static delayQueue q = new STATIC DELAYQUE Q = New DELAYQUEUE (); / ** * Producer: Put the object to the queue * / private static class producer imports runnable {public void Run () {while {q.put (new object ()); thread Catch (Exception E) {thread.currentthread (). Interrupt ();}}}} / ** * Consumer: Remove 5000 Information from Queue * / Private Static Class Consumer IMPLEments Runnable {Private Static Final Int Max = 50000; / ** * * @Throws CassCastException When the producer calls the DRAINTO method handling This error will occur when you enter the Object object.

转载请注明原文地址:https://www.9cbs.com/read-63095.html

New Post(0)