Getting to know the Queue queue

1. wait and notify simulate Queue

1.1 basic knowledge of wait / notify

Thread communication concept: Threads are independent individuals in the operating system, but these individuals cannot become a whole without special treatment, and communication between threads has become one of the necessary methods for the whole.

Use the wait/notify methods to communicate between threads:

1) wait and notify must be used with the synchronized keyword

2) The wait method releases the lock, and the notify method does not release the lock.

1.2 wait / notify 模拟BlockingQueue

BlockingQueue: It is a queue and supports blocking mechanism, blocking put and get data. We want to implement LinkedBlockingQueue The following two simple methods put and take

put(an object): Add an object to the BlockingQueue. If there is no space in the BlockingQueue, the thread calling this method will be blocked until there is space in the BlockingQueue to continue.

take: Take the object ranked first in the BlockingQueue. If the BlockingQueue is empty, block entering the waiting state until the BlockingQueue has new data added.

[java] view plain copy

  1. import java.util.LinkedList;  
  2. import java.util.concurrent.TimeUnit;  
  3. import java.util.concurrent.atomic.AtomicInteger;  
  4.   
  5. public class MyQueue {  
  6.       
  7.     //1 requires a collection of holding elements   
  8.     private LinkedList<Object> list = new LinkedList<Object>();  
  9.     //2 requires a counter AtomicInteger (atomicity)  
  10.     private AtomicInteger count = new AtomicInteger(0);  
  11.     //3 Need to set upper and lower bounds  
  12.     private final int minSize = 0;  
  13.     private final int maxSize ;  
  14.       
  15.     //4 Constructor  
  16.     public MyQueue(int size){  
  17.         this.maxSize = size;  
  18.     }  
  19.       
  20.     //5 Initialize an object for locking  
  21.     private final Object lock = new Object();  
  22.       
  23.     //put(anObject): Add anObject to the BlockingQueue. If the BlockQueue has no space, the thread calling this method will be blocked until there is space in the BlockingQueue to continue.  
  24.     public void put(Object obj){  
  25.         synchronized (lock) {  
  26.             while(count.get() == this.maxSize){  
  27.                 try {  
  28.                     lock.wait(); // When the Queue has no space, the thread is blocked  
  29.                 } catch (InterruptedException e) {  
  30.                     e.printStackTrace ();  
  31.                 }  
  32.             }  
  33.             //1 add element  
  34.             list.add(obj);  
  35.             //2 count up  
  36.             count.incrementAndGet();  
  37.             //3 After adding an element, notify another thread (wake up), and there is one more element in the queue, which can be removed.  
  38.             lock.notify();  
  39.             System.out.println("The newly added element is: " + obj);  
  40.         }  
  41.     }  
  42.       
  43.     //take: Take the object ranked first in the BlockingQueue. If the BlockingQueue is empty, block and enter the waiting state until the BlockingQueue has new data added.  
  44.     public Object take(){  
  45.         Object ret = null;  
  46.         synchronized (lock) {  
  47.             while(count.get() == this.minSize){  
  48.                 try {  
  49.                     lock.wait();  
  50.                 } catch (InterruptedException e) {  
  51.                     e.printStackTrace ();  
  52.                 }  
  53.             }  
  54.             //1 do the element removal operation  
  55.             ret = list.removeFirst();  
  56.             //2 counter decrements  
  57.             count.decrementAndGet();  
  58.             //3 After removing the element, wake up another thread, the queue has fewer elements, and the operation can be added again  
  59.             lock.notify();  
  60.         }  
  61.         return ret;  
  62.     }  
  63.       
  64.     public int getSize(){  
  65.         return this.count.get();  
  66.     }  
  67.       
  68.     public static void main(String[] args) {  
  69.         final MyQueue mq = new MyQueue(5);  
  70.         mq.put("a");  
  71.         mq.put("b");  
  72.         mq.put("c");  
  73.         mq.put("d");  
  74.         mq.put("e");  
  75.         System.out.println("Length of current container: " + mq.getSize());  
  76.         Thread t1 = new Thread(new Runnable() {  
  77.             @Override  
  78.             public void run() {  
  79.                 mq.put("f");  
  80.                 mq.put("g");  
  81.             }  
  82.         },"t1");  
  83.         Thread t2 = new Thread(new Runnable() {  
  84.             @Override  
  85.             public void run() {  
  86.                 Object o1 = mq.take();  
  87.                 System.out.println("The removed element is: " + o1);  
  88.                 Object o2 = mq.take();  
  89.                 System.out.println("The removed element is: " + o2);  
  90.             }  
  91.         },"t2");  
  92.         t1.start();  
  93.         try {  
  94.             TimeUnit.SECONDS.sleep(2);  
  95.         } catch (InterruptedException e) {  
  96.             e.printStackTrace ();  
  97.         }  
  98.         t2.start();  
  99.     }  
  100.       
  101. }  

It can be seen from the printed information that when the t2 thread removes the data, the t1 thread starts to add data

 

2. Concurrent Queue

2.1 Introduction to Queue

The main implementation of Queue is shown in the following figure. Queue is mainly divided into two categories, one is the high-performance queue ConcurrentLinkedQueue; the other is the blocking queue BlockingQueue

 

 

2.2 ConcurrentLinkedQueue interface

ConcurrentLinkedQueue: It is a queue suitable for high concurrency scenarios. It achieves high performance under high concurrency in a lock-free manner. Usually, ConcurrentLinkedQueue has better performance than BlockingQueue. It is an unbounded thread-safe queue based on linked nodes. The elements of this queue follow the principle of first-in, first-out. The head is added first and the tail is added last. The queue does not allow null elements.

Important methods of ConcurrentLinkedQueue:

Both add() and offer() are adding elements, and there is no difference in the queue

Both poll() and peek() take the head element node, the difference is that the former will delete the element, the latter will not

[java] view plain copy

  1. import java.util.concurrent.ConcurrentLinkedQueue;  
  2.   
  3. public class MyConcurrentLinkedQueue {  
  4.   
  5.     public static void main(String[] args) throws Exception {  
  6.           
  7.         //High-performance non-blocking unbounded queue: ConcurrentLinkedQueue  
  8.         ConcurrentLinkedQueue<String> q = new ConcurrentLinkedQueue<String>();  
  9.         q.offer("a");  
  10.         q.offer("b");  
  11.         q.offer("c");  
  12.         q.offer("d");  
  13.         q.add("e");  
  14.           
  15.         System.out.println(q.poll()); // print result: a (take the element from the head and delete it from the queue)  
  16.         System.out.println(q.size()); // print result: 4 (the element is reduced by one after poll is executed)  
  17.         System.out.println(q.peek()); // print result: b (a is removed, the first element is b)  
  18.         System.out.println(q.size()); // print result: 4 (peek does not remove elements)  
  19.           
  20.     }  
  21. }  

 

2.3 BlockingQueue interface

ArrayBlockingQueue: Array-based blocking queue implementation, internally, maintains a fixed-length array to cache data objects in the queue. It does not implement read-write separation internally, which means that production and consumption cannot be completely parallel. The length needs to be defined, you can specify FIFO or FIFO, it is a bounded queue.

[java] view plain copy

  1. import java.util.concurrent.ArrayBlockingQueue;  
  2. import java.util.concurrent.TimeUnit;  
  3.   
  4. public class MyArrayBlockingQueue {  
  5.   
  6.     public static void main(String[] args) throws Exception {  
  7.         ArrayBlockingQueue<String> array = new ArrayBlockingQueue<String>(5); // You can try to change the queue length from 3 to 5  
  8.         array.offer("offer method returns true if the data is inserted successfully, otherwise returns false");  
  9.         array.offer("Insert data after 3 seconds", 3, TimeUnit.SECONDS);  
  10.         array.put("put method will block waiting if it exceeds the length");  
  11.         array.add("add method will prompt error message when the length exceeds java.lang.IllegalStateException"); // java.lang.IllegalStateException: Queue full  
  12.         System.out.println(array.offer("true or false", 3, TimeUnit.SECONDS));  
  13.         System.out.println(array);  
  14.     }  
  15. }  

 

LinkedBlockingQueue: List-based blocking queue, similar to ArrayBlockingQueue, it maintains a data buffer queue (the queue is composed of a linked list). The reason why it can efficiently process concurrent data is that its internal implementation adopts separate locks (read and write). Separating the two locks), allowing for fully parallel running of producer and consumer operations. is an unbounded queue

The usage is similar to ArrayBlockingQueue, offer, put, add. The difference is that LinkedBlockingQueue is an unbounded queue. When initializing, you can set a length or not. The drainTo(collection, maximum length of the collection) method can intercept the length from the LinkedBlockingQueue to another collection.

 

SynchronousQueue: An unbuffered queue, the data produced by the survivor will be directly acquired and consumed by the consumer.

 

What scenarios are the above three queues used for? For example: take the subway. When there are few people, when swiping the card, one person can swipe directly without waiting. This uses SynchronousQueue. During the rush hour, there are a lot of people. When you swipe your card, you need to queue up. This uses the LinkedBlockingQueue unbounded queue. The peak holiday season is full of people. If the LinkedBlockingQueue is used, it is unbounded. If too many people come in, it will affect the normal work of the subway station. At this time, the bounded queue ArrayBlockingQueue should be used.

 

PriorityBlockingQueue: priority-based blocking queue (priority judgment is determined by the Compator object passed in by the constructor, that is to say, the object passed into the queue must implement the Comparable interface). When implementing PriorityBlockingQueue, the internal control thread synchronization lock adopts is a fair lock, which is an unbounded queue.

The object passed into the queue: Task

[java] view plain copy

  1. public class Task implements Comparable<Task>{  
  2.       
  3.     private int id ;  
  4.     private String name;  
  5.       
  6.     public int getId() {  
  7.         return id;  
  8.     }  
  9.     public void setId(int id) {  
  10.         this.id = id;  
  11.     }  
  12.     public String getName() {  
  13.         return name;  
  14.     }  
  15.     public void setName(String name) {  
  16.         this.name = name;  
  17.     }  
  18.       
  19.     @Override  
  20.     public int compareTo(Task task) {  
  21.         return this.id > task.id ? 1 : (this.id < task.id ? -1 : 0);    
  22.     }  
  23.       
  24.     public String toString(){  
  25.         return this.id + "," + this.name;  
  26.     }  
  27.       
  28. }  

PriorityBlockingQueue ordering:

[java] view plain copy

  1. import java.util.concurrent.PriorityBlockingQueue;  
  2.   
  3. public class MyPriorityBlockingQueue {  
  4.       
  5.     public static void main(String[] args) throws Exception{  
  6.           
  7.         PriorityBlockingQueue<Task> q = new PriorityBlockingQueue<Task>();  
  8.           
  9.         // set from large to small  
  10.         Task t1 = new Task();  
  11.         t1.setId (1);  
  12.         t1.setName("id为1");  
  13.         Task t2 = new Task();  
  14.         t2.setId(4);  
  15.         t2.setName("id为4");  
  16.         Task t3 = new Task();  
  17.         t3.setId(9);  
  18.         t3.setName("id为9");  
  19.         Task t4 = new Task();  
  20.         t4.setId(16);  
  21.         t4.setName("id为16");  
  22.         Task t5 = new Task();  
  23.         t5.setId(5);  
  24.         t5.setName("id为5");  
  25.           
  26.         // Deliberately disrupt the order into the queue  
  27.         q.add(t3);  
  28.         q.add(t4);  
  29.         q.add(t1);  
  30.         q.add(t2);  
  31.         q.add(t5);  
  32.           
  33.         System.out.println("Initial queue container: " + q);  
  34.         System.out.println("The first element: " + q.take()); // Sort after take (sort output after taking value)  
  35.         System.out.println("Container after executing take method: " + q);  
  36.           
  37.     }  
  38. }  

 

DelayQueue: A Queue with a delay time. The element can only be obtained from the queue when the specified delay time is reached. The elements in the DelayQueue must implement the Delayed interface. DelayQueue is a queue with no size limit. There are many application scenarios. ,

For example, removing cached timeout data, task timeout processing, closing idle connections, etc.

Excerpt from online code:

[java] view plain copy

  1. import java.util.concurrent.Delayed;  
  2. import java.util.concurrent.TimeUnit;  
  3.   
  4. public class Wangmin implements Delayed {    
  5.       
  6.     private String name;    
  7.     //ID card    
  8.     private String id;    
  9.     //deadline    
  10.     private long endTime;    
  11.     //Define the time tool class  
  12.     private TimeUnit timeUnit = TimeUnit.SECONDS;  
  13.         
  14.     public Wangmin(String name,String id,long endTime){    
  15.         this.name=name;    
  16.         this.id=id;    
  17.         this.endTime = endTime;    
  18.     }    
  19.         
  20.     public String getName(){    
  21.         return this.name;    
  22.     }    
  23.         
  24.     public String getId(){    
  25.         return this.id;    
  26.     }    
  27.         
  28.     /**  
  29.      * Used to determine whether the deadline is reached  
  30.      */    
  31.     @Override    
  32.     public long getDelay(TimeUnit unit) {   
  33.         //return unit.convert(endTime, TimeUnit.MILLISECONDS) - unit.convert(System.currentTimeMillis(), TimeUnit.MILLISECONDS);  
  34.         return endTime - System.currentTimeMillis();  
  35.     }    
  36.     
  37.     /**  
  38.      * For mutual batch comparison and sorting  
  39.      */    
  40.     @Override    
  41.     public int compareTo(Delayed delayed) {    
  42.         Wangmin w = (Wangmin)delayed;    
  43.         return this.getDelay(this.timeUnit) - w.getDelay(this.timeUnit) > 0 ? 1:0;    
  44.     }    
  45. }    

 

[java] view plain copy

  1. import java.util.concurrent.DelayQueue;  
  2.   
  3. public class WangBa implements Runnable {    
  4.       
  5.     private DelayQueue<Wangmin> queue = new DelayQueue<Wangmin>();    
  6.     public boolean yinye =true;    
  7.         
  8.     public void shangji(String name,String id,int money){    
  9.         Wangmin man = new Wangmin(name, id, 1000 * money + System.currentTimeMillis());    
  10.         System.out.println("screen name"+man.getName()+"ID card"+man.getId()+"payment"+money+"block, start on the machine...");    
  11.         this.queue.add(man);    
  12.     }    
  13.         
  14.     public void xiaji(Wangmin man){    
  15.         System.out.println("Screen name"+man.getName()+"ID card"+man.getId()+"Time to get off the plane...");    
  16.     }    
  17.     
  18.     @Override    
  19.     public void run() {    
  20.         while(yinye){    
  21.             try {    
  22.                 Wangmin man = queue.take();    
  23.                 xiaji(man);    
  24.             } catch (InterruptedException e) {    
  25.                 e.printStackTrace ();    
  26.             }    
  27.         }    
  28.     }    
  29.         
  30.     public static void main(String args[]){    
  31.         try{    
  32.             System.out.println("Internet cafes are open for business");    
  33.             WangBa siyu = new WangBa();    
  34.             Thread shangwang = new Thread(siyu);    
  35.             shangwang.start();    
  36.                 
  37.             siyu.shangji("Passenger A", "123", 1);    
  38.             siyu.shangji("Passerby B", "234", 10);    
  39.             siyu.shangji("Passenger C", "345", 5);    
  40.         }    
  41.         catch(Exception e){    
  42.             e.printStackTrace ();  
  43.         }    
  44.     
  45.     }    
  46. }    

 

 

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=325079476&siteId=291194637