//A delayed fetch queue based on binary heap priority. //Look at the constructor first. public DelayQueue() {} public DelayQueue(Collection<? extends E> c) { this.addAll(c); } //Insert the collection into the internal PriorityQueue. public boolean addAll(Collection<? extends E> c) { if (c == null) throw new NullPointerException(); if (c == this) throw new IllegalArgumentException(); boolean modified = false; for (E e : c) if (add(e)) modified = true; return modified; } public boolean add(E e) { if (offer(e)) return true; else throw new IllegalStateException("Queue full"); } //Insert elements are inserted into the internal PriorityQueue. public boolean offer(E e) { final ReentrantLock lock = this.lock; lock.lock(); try { q.offer(e); //If the header element is inserted (that is, the current header element has changed) if (q.peek() == e) { //Set the leader thread to null leader = null; // wake up the waiting thread available.signal(); } return true; } finally { lock.unlock(); } } public boolean offer(E e, long timeout, TimeUnit unit) { return offer(e); } public void put(E e) { offer(e); } // get the element but don't remove it public E peek() { final ReentrantLock lock = this.lock; lock.lock(); try { //Use the underlying priorityQueue implementation. return q.peek(); } finally { lock.unlock(); } } //Get the header element If the header element is empty or it has not been dequeued, return null. public E poll() { final ReentrantLock lock = this.lock; lock.lock(); try { // get the header element E first = q.peek(); //If the header element is empty or the obtained header element has not been dequeued, return null if (first == null || first.getDelay(TimeUnit.NANOSECONDS) > 0) return null; else return q.poll(); } finally { lock.unlock(); } } public E poll(long timeout, TimeUnit unit) throws InterruptedException { long nanos = unit.toNanos(timeout); final ReentrantLock lock = this.lock; lock.lockInterruptibly(); try { for (;;) { E first = q.peek(); //if empty if (first == null) { // time out and return null if (nanos <= 0) return null; else //Suspend the current thread nanos time nanos = available.awaitNanos(nanos); } else { long delay = first.getDelay(TimeUnit.NANOSECONDS); // when it's time to take it out if (delay <= 0) return q.poll(); // time out and return null if (nanos <= 0) return null; //If the waiting time is less than the dequeue time or the leader thread !=null, suspend the current thread if (nanos < delay || leader != null) nanos = available.awaitNanos(nanos); else { //If there is no other leader thread, set itself as the leader thread Thread thisThread = Thread.currentThread(); leader = thisThread; try { long timeLeft = available.awaitNanos(delay); nanos -= delay - timeLeft; } finally { //if the leader is himself if (leader == thisThread) leader = null; } } } } } finally { // release the lock if (leader == null && q.peek() != null) available.signal(); lock.unlock(); } } //Blockable get queue head node public E take() throws InterruptedException { final ReentrantLock lock = this.lock; lock.lockInterruptibly(); try { for (;;) { E first = q.peek(); // if not obtained, wait if (first == null) available.await(); else { long delay = first.getDelay(TimeUnit.NANOSECONDS); //return the arrival queue dequeue time if (delay <= 0) return q.poll(); //If the leader is not equal to null, block the current thread and let the leader thread take the current element else if (leader != null) available.await(); else { Thread thisThread = Thread.currentThread(); //The current thread is set to the leader leader = thisThread; try { //Wait for the delay time to wake up available.awaitNanos(delay); } finally { //After waking up, if I am the leader, let other threads become the leader. if (leader == thisThread) leader = null; } } } } } finally { //If the leader is empty and there is a head to wake up other threads. if (leader == null && q.peek() != null) available.signal(); lock.unlock(); } } /** The leader thread is the thread that is currently getting the head node. When the offer is made, if the inserted element becomes the head node, At this time, the leader is set to null, and the competition for the leader is re-competed. DelayQueen uses a PriorityQueen class implementation internally, so the priority of the insertion order can be guaranteed. Then according to the getDelay method that implements the Delayed interface, get whether the element has reached the dequeue time. */ //get the queue length public int size() { final ReentrantLock lock = this.lock; lock.lock(); try { return q.size(); } finally { lock.unlock(); } } //Get the capacity (there is no capacity limit, so return the maximum value of integer) public int remainingCapacity() { return Integer.MAX_VALUE; } // remove element public boolean remove(Object o) { final ReentrantLock lock = this.lock; lock.lock(); try { return q.remove(o); } finally { lock.unlock(); } } public Object[] toArray() { final ReentrantLock lock = this.lock; lock.lock(); try { return q.toArray(); } finally { lock.unlock(); } } public <T> T[] toArray(T[] a) { final ReentrantLock lock = this.lock; lock.lock(); try { return q.toArray(a); } finally { lock.unlock(); } } // remove the available elements from the queue and wrap them in the collection public int drainTo (Collection <? super E> c) { if (c == null) throw new NullPointerException(); if (c == this) throw new IllegalArgumentException(); final ReentrantLock lock = this.lock; lock.lock(); try { int n = 0; for (;;) { E first = q.peek(); if (first == null || first.getDelay(TimeUnit.NANOSECONDS) > 0) break; c.add(q.poll()); ++n; } return n; } finally { lock.unlock(); } } // Remove at most maxElements available elements from the collection. public int drainTo (Collection <? super E> c, int maxElements) { if (c == null) throw new NullPointerException(); if (c == this) throw new IllegalArgumentException(); if (maxElements <= 0) return 0; final ReentrantLock lock = this.lock; lock.lock(); try { int n = 0; while (n < maxElements) { E first = q.peek(); if (first == null || first.getDelay(TimeUnit.NANOSECONDS) > 0) break; c.add(q.poll()); ++n; } return n; } finally { lock.unlock(); } }
Read DelayQueen source code
Guess you like
Origin http://43.154.161.224:23101/article/api/json?id=326489172&siteId=291194637
Recommended
Ranking