Java中的DelayQueue
时间:2020-01-09 10:35:11 来源:igfitidea点击:
Java中的DelayQueue是BlockingQueue接口的实现,并且是java.util.concurrent包的一部分。 Java中的DelayQueue是一个无界队列,它与ArrayBlockingQueue是有界队列不同。
延迟接口
Java DelayQueue只能存储类型为Delayed的元素。 Java中有一个接口Delayed,它定义了这些元素的类型。
延迟接口用于定义在给定延迟后应作用的对象的类型。
public interface Delayed extends Comparable<Delayed> { long getDelay(TimeUnit unit); }
getDelay(TimeUnit unit)方法以给定的时间单位返回与此对象关联的剩余延迟。
由于Delayed接口还扩展了Comparable接口,因此此接口的实现必须定义一个compareTo()方法,该方法提供与其getDelay方法一致的顺序。
DelayQueue过期的元素
从Java中的DelayQueue中,只能在元素的延迟到期后才能使用它。元素是从队列的开头获取的,这意味着队列的开头是该Delayed元素,其延迟在过去最远时过期。
当元素的getDelay(TimeUnit.NANOSECONDS)方法返回的值小于或者等于零时,队列中的元素就会过期。
诸如take()之类的阻塞方法将等待,直到该队列上具有过期延迟的元素可用。
Java中的DelayQueue的功能
- DelayQueue存储类型为Delayed的元素。接口延迟定义了这些延迟元素的类型。
- 只有在延迟到期后才能从DelayQueue中获取元素。
- DelayQueue是线程安全的实现。
- Java中的DelayQueue不允许添加null元素。
Java DelayQueue构造函数
- DelayQueue()–创建一个最初为空的新DelayQueue。
- DelayQueue(Collection <?扩展E> c)-创建一个DelayQueue,最初包含给定的Delayed实例集合的元素。
DelayQueue Java示例
这是使用DelayQueue的生产者-消费者示例。由于DelayQueue存储类型为Delayed的元素,因此我们也需要实现Delayed接口。
private long expiryTime; DelayQElement(String queueElement, long delay){ this.queueElement = queueElement; // Expirytime is current time + delay this.expiryTime = System.currentTimeMillis() + delay; System.out.println("Putting queueElement " + queueElement + " expiry " + this.expiryTime); } @Override public long getDelay(TimeUnit unit) { long diff = expiryTime - System.currentTimeMillis(); return unit.convert(diff, TimeUnit.MILLISECONDS); } @Override public int compareTo(Delayed o) { if(this.getDelay(TimeUnit.MILLISECONDS) < o.getDelay(TimeUnit.MILLISECONDS)){ return -1; } if(this.getDelay(TimeUnit.MILLISECONDS) > o.getDelay(TimeUnit.MILLISECONDS)){ return 1; } return 0; } public String toString(){ return queueElement + " Expiry Time= " + expiryTime; } }
使用DelayQueue的生产者-消费者
public class DQDemo { public static void main(String[] args) { // delay of 3 seconds final long delay = 3000; BlockingQueue<DelayQElement> delayQ = new DelayQueue<DelayQElement>(); // Producer thread new Thread(()->{ for(int i = 0; i < 5; i++){ try { delayQ.put(new DelayQElement("Element"+i, delay)); Thread.sleep(50); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } } }).start(); // Consumer thread new Thread(()->{ for(int i = 0; i < 5; i++){ try { System.out.println(" Consumer got - " + delayQ.take().toString()); Thread.sleep(100); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } } }).start(); } }
输出:
Putting queueElement Element0expiry 1541830388935 Putting queueElement Element1expiry 1541830388998 Putting queueElement Element2expiry 1541830389060 Putting queueElement Element3expiry 1541830389123 Putting queueElement Element4expiry 1541830389185 Consumer got - Element0 Expiry Time= 1541830388935 Consumer got - Element1 Expiry Time= 1541830388998 Consumer got - Element2 Expiry Time= 1541830389060 Consumer got - Element3 Expiry Time= 1541830389123 Consumer got - Element4 Expiry Time= 1541830389185
如我们所见,元素在元素过期后从队列中取出。
DelayQueue类方法
这是Java中DelayQueue类的一些方法的列表。
- add(E e)–将指定的元素插入此延迟队列。
- clear()–以原子方式从此延迟队列中删除所有元素。
- offer(E e)–将指定的元素插入此延迟队列。
- peek()–检索但不删除此队列的头,如果此队列为空,则返回null。
- poll()–检索并删除此队列的头部,如果此队列没有延迟过期的元素,则返回null。
- poll(long timeout,TimeUnit unit)–检索并删除此队列的头部,如有必要,请等待直到该队列上具有过期延迟的元素可用,或者指定的等待时间到期为止。
- put(E e)–将指定的元素插入此延迟队列。
- remove(Object o)–从该队列中移除指定元素的单个实例(如果存在),无论该元素是否已过期。
- take()–检索并删除此队列的头部,如有必要,请等待直到延迟过期的元素在此队列上可用。