The Queue interface is at the same level as List and Set, and both inherit the Collection interface. LinkedList implements the Queue interface. The Queue interface narrows access to the LinkedList method (that is, if the parameter type in the method is a Queue, it can only access the methods defined by the Queue interface, and cannot directly access the non-Queue methods of the LinkedList), so that only the appropriate method can be used. BlockingQueue inherits the Queue interface.
A queue is a data structure. It has two basic operations: adding an element at the end of the queue, and removing an element from the head of the queue means that the queue manages data in a first-in-first-out way. If you try to add an element to a full blocking queue or remove a metasector from an empty blocking queue, it will cause the thread to block. Blocking queues is a useful tool when cooperating with multiple threads. Worker threads can regularly store intermediate results in a blocking queue while other worker threads take intermediate results out and modify them in the future. The queue automatically balances the load. If the first thread set runs slower than the second, the second thread set will block while waiting for the result. If the first thread set runs fast, it will wait for the second thread set to catch up. The following table shows the operations of blocking queues in jdk1.5:
add Add a metasearch If the queue is full, throw an IIIegaISlabEepeplian exception
remove Remove and return the element at the head of the queue. If the queue is empty, a NoSuchElementException exception is thrown.
element Returns the element at the head of the queue. If the queue is empty, a NoSuchElementException exception is thrown.
offer Add an element and returns true If the queue is full, return false
poll Removes and returns the element in the head of the queue. If the queue is empty, return null.
peek Returns the element at the head of the queue. If the queue is empty, return null
put add an element if the queue is full, blocking
take Remove and return the element at the head of the queue. If the queue is empty, blocks
remove, element, offer, poll, and peek actually belong to the Queue interface.
Operations that block queues can be divided into the following three categories according to their responses: aad, removee, and element operations throw exceptions when you try to add elements to a full queue or get elements from an empty queue. Of course, in a multithreaded program, the queue may become full or empty at any time, so you may want to use the offer, poll, peek methods. These methods simply give an error message when the task cannot be completed without throwing an exception.
Note: Poll and peek methods errors and return null. Therefore, it is illegal to insert a null value into the queue.
There are also offer and poll method variants with timeouts, for example, the following calls:
boolean success = q.offer(x,100,TimeUnit.MILLISECONDS);
Try inserting an element into the tail of the queue in 100 milliseconds. If successful, return true immediately; otherwise, when the timeout is reached, return false. Similarly, call:
Object head = q.poll(100, TimeUnit.MILLISECONDS);
If the queue header element is successfully removed within 100 milliseconds, the header element is returned immediately; otherwise, null is returned when the timeout is reached.
Finally, we have blocking operations put and take. The put method blocks when the queue is full, and the take method blocks when the queue is empty.
The java.ulil.concurrent package provides 4 variants of blocking queues. By default, the capacity of LinkedBlockingQueue is not upper limit (it is inaccurate. The capacity is Integer.MAX_VALUE when not specified. If not, how can it be blocked when put), but you can also choose to specify its maximum capacity. It is a queue based on a linked list, which sorts elements by FIFO (first in first out).
ArrayBlockingQueue needs to specify capacity during construction, and you can choose whether fairness is required. If the fair parameter is set true, the thread with the longest waiting time will be processed first (in fact, this fairness is achieved by setting ReentrantLock to true: that is, the thread with the longest waiting time will operate first). Typically, fairness can cost you performance and only use it when it is really necessary. It is an array-based blocking loop queue that sorts elements according to FIFO (first in first out) principle.
PriorityBlockingQueue is a queue with priority, not a first-in-first-out queue. Elements are removed in priority order, and the queue has no upper limit (I looked at the source code. PriorityBlockingQueue is a re-wrapping of PriorityQueue, which is based on the heap data structure. PriorityQueue has no capacity limit, just like ArrayList, so it will not be blocked when put on a priority blocking queue. Although this queue is logically unbounded, attempting to perform an add operation may cause an OutOfMemoryError because of the resource being exhausted), but if the queue is empty, the operation taking of the element will block, so its search operation takes is blocked. In addition, the elements entering the queue must have comparative capabilities.
Finally, DelayQueue (implemented based on PriorityQueue) is an unbounded blocking queue that stores Delayed elements, and elements can only be extracted when the delay expires. The head of this queue is the Delayed element with the longest storage time after the delay expires. If none of the delays have expired, the queue has no headers and poll will return null. When the getDelay(TimeUnit.NANOSECONDS) method of an element returns a value less than or equal to zero, the expiration occurs and poll removes the element. This queue does not allow null elements. Here is the delay interface:
Java code
public interface Delayed extends Comparable<Delayed> { long getDelay(TimeUnit unit); }The element that puts DelayQueue will also implement the compareTo method, which uses this to sort the elements.
The following example shows how to use a blocking queue to control a thread set. The program searches for all files in one directory and all its subdirectories, and prints out a list of files containing the specified keywords. As can be seen from the following examples, the two significant benefits of using blocking queues are: multi-threaded operation of common queues do not require additional synchronization. In addition, the queue will automatically balance the load, that is, if the processing (both sides of production and consumption) is processed quickly, it will be blocked, thereby reducing the processing speed gap between the two sides. The following is the specific implementation:
Java code
public class BlockingQueueTest { public static void main(String[] args) { Scanner in = new Scanner(System.in); System.out.print("Enter base directory (eg /usr/local/jdk5.0/src): "); String directory = in.nextLine(); System.out.print("Enter keyword (eg volatile): "); String keyword = in.nextLine(); final int FILE_QUEUE_SIZE = 10;// Blocking queue size final int SEARCH_THREADS = 100;// Number of keyword search threads// Blocking queue based on ArrayBlockingQueueBlockingQueue<File> queue = new ArrayBlockingQueue<File>( FILE_QUEUE_SIZE); //Only start one thread to search the directory FileEnumerationTask enumerator = new FileEnumerationTask(queue, new File(directory)); new Thread(enumerator).start(); //Start 100 threads to search for the specified keyword in the file for (int i = 1; i <= SEARCH_THREADS; i++) new Thread(new SearchTask(queue, keyword)).start(); } } class FileEnumerationTask implements Runnable { //The dumb metafile object is placed at the end of the blocking queue to indicate that the file has been traversed public static File DUMMY = new File(""); private BlockingQueue<File> queue; private File startingDirectory; public FileEnumerationTask(BlockingQueue<File> queue, File startingDirectory) { this.queue = queue; this.startingDirectory = startingDirectory; } public void run() { try { enumerate(startingDirectory); queue.put(DUMMY);//Execute here to indicate that the file in the specified directory has been traversed} catch (InterruptedException e) { } } // Put all files in the specified directory into the blocking queue as File objects public void enumerate(File directory) throws InterruptedException { File[] files = directory.listFiles(); for (File file : files) { if (file.isDirectory()) enumerate(file); else //Put the element to the end of the queue. If the queue is full, block queue.put(file); } } } class SearchTask implements Runnable { private BlockingQueue<File> queue; private String keyword; public SearchTask(BlockingQueue<File> queue, String keyword) { this.queue = queue; this.keyword = keyword; } public void run() { try { boolean done = false; while (!done) { //Fetch out the first element of the queue. If the queue is empty, block File file = queue.take(); if (file == FileEnumerationTask.DUMMY) { //Fetch it out and put it in so that other threads will end quickly when reading it queue.put(file); done = true; } else search(file); } } catch (IOException e) { e.printStackTrace(); } catch (InterruptedException e) { } } public void search(File file) throws IOException { Scanner in = new Scanner(new FileInputStream(file)); int lineNumber = 0; while (in.hasNextLine()) { lineNumber++; String line = in.nextLine(); if (line.contains(keyword)) System.out.printf("%s:%d:%s%n", file.getPath(), lineNumber, line); } in.close(); } } Original link: http://www.cnblogs.com/end/archive/2012/10/25/2738493.html
The above is all the content of this article. I hope it will be helpful to everyone's learning and I hope everyone will support Wulin.com more.