`

Java DelayQueue使用实例

阅读更多

DelayQueue是一个支持延时获取元素的无界阻塞队列。队列使用PriorityQueue来实现。队列中的元素必须实现Delayed接口,在创建元素时可以指定多久才能从队列中获取当前元素。只有在延迟期满时才能从队列中提取元素。我们可以将DelayQueue运用在以下应用场景:

  • 缓存系统的设计:可以用DelayQueue保存缓存元素的有效期,使用一个线程循环查询DelayQueue,一旦能从DelayQueue中获取元素时,表示缓存有效期到了。
  • 定时任务调度。使用DelayQueue保存当天将会执行的任务和执行时间,一旦从DelayQueue中获取到任务就开始执行,从比如TimerQueue就是使用DelayQueue实现的。

   

具有过期时间的缓存

 

 

package test;

import java.util.Random;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.DelayQueue;
import java.util.concurrent.Delayed;
import java.util.concurrent.TimeUnit;

public class SessionCache<K, V> {

    public ConcurrentHashMap<K, V> map = new ConcurrentHashMap<K, V>();
    public DelayQueue<DelayedItem<K>> queue = new DelayQueue<DelayedItem<K>>();
    
    
    static class SingletonHolder {    
        static SessionCache instance = new SessionCache();    
    }    
       
    public static SessionCache getInstance() {    
        return SingletonHolder.instance;    
    }  
    

    public void put(K k, V v, long liveTime) {
        V v2 = map.put(k, v);
        DelayedItem<K> tmpItem = new DelayedItem<K>(k, liveTime);
        if (v2 != null) {
            queue.remove(tmpItem);
        }
        queue.put(tmpItem);
    }

    public SessionCache() {
        Thread t = new Thread() {
            @Override
            public void run() {
                dameonCheckOverdueKey();
            }
        };
        t.setDaemon(true);
        t.start();
    }

    public void dameonCheckOverdueKey() {
        while (true) {
            DelayedItem<K> delayedItem = queue.poll();
            if (delayedItem != null) {
                map.remove(delayedItem.getT());
                System.out.println(System.nanoTime() + " remove " + delayedItem.getT() + " from cache");
            }
            try {
                Thread.sleep(300);
            } catch (Exception e) {
                // TODO: handle exception
            }
        }
    }

    public static void main(String[] args) throws InterruptedException {
        Random random = new Random();
        int cacheNumber = 10;
        Long liveTime = 200000000L;
        
        SessionCache cache = SessionCache.getInstance();
        for (int i = 0; i < cacheNumber; i++) {
            liveTime = liveTime + random.nextInt(10) * 10000;
            System.out.println(i + "  " + liveTime);
            cache.put(i + "", i + "", liveTime);
            liveTime = 200000000L;

        }

        Thread.sleep(100000);
        System.out.println();
    }

}

class DelayedItem<T> implements Delayed {

    private T t;
    private long liveTime;
    private long removeTime;

    public DelayedItem(T t, long liveTime) {
        this.setT(t);
        this.liveTime = liveTime;
        this.removeTime = TimeUnit.NANOSECONDS.convert(liveTime, TimeUnit.NANOSECONDS) + System.nanoTime();
    }

    @Override
    public int compareTo(Delayed o) {
        if (o == null)
            return 1;
        if (o == this)
            return 0;
        if (o instanceof DelayedItem) {
            DelayedItem<T> tmpDelayedItem = (DelayedItem<T>) o;
            if (liveTime > tmpDelayedItem.liveTime) {
                return 1;
            } else if (liveTime == tmpDelayedItem.liveTime) {
                return 0;
            } else {
                return -1;
            }
        }
        long diff = getDelay(TimeUnit.NANOSECONDS) - o.getDelay(TimeUnit.NANOSECONDS);
        return diff > 0 ? 1 : diff == 0 ? 0 : -1;
    }

    @Override
    public long getDelay(TimeUnit unit) {
        return unit.convert(removeTime - System.nanoTime(), unit);
    }

    public T getT() {
        return t;
    }

    public void setT(T t) {
        this.t = t;
    }

    @Override
    public int hashCode() {
        return t.hashCode();
    }

    @Override
    public boolean equals(Object object) {
        if (object instanceof DelayedItem) {
            return object.hashCode() == hashCode() ? true : false;
        }
        return false;
    }
    
    
}

 

 

 参考:http://ifeve.com/java-blocking-queue/

 

 

 

 

分享到:
评论

相关推荐

    DelayQueue延迟队列和Redis缓存实现订单自动取消功能

    2. 实例化一个DelayQueue,并放入待处理的订单对象。这些订单将在指定的延迟时间后被处理。 3. 使用Jedis或者其他Redis客户端连接到Redis服务器,将订单信息存储为键值对,键是订单号,值是订单数据,同时设置键的...

    JDK自带的延迟队列-DelayQueue

    在Java的并发编程中,`DelayQueue`是一个非常特殊的队列,它属于并发包`java.util.concurrent`的一部分。`DelayQueue`是一个基于优先级队列(PriorityQueue)实现的无界阻塞队列,它的主要特性是元素只有在达到指定...

    java实现一个小程序语句的延迟执行的小demo

    首先,Java提供了多种方式来实现延迟执行,例如使用`java.util.Timer`类、`java.util.concurrent.DelayQueue`或者`java.util.concurrent.ScheduledExecutorService`。这里我们将重点讨论`ScheduledExecutorService`...

    java学习(基于Java阻塞队列的搜索实例).pdf

    在Java中,`java.util.concurrent`包提供了多种阻塞队列实现,包括`LinkedBlockingQueue`、`ArrayBlockingQueue`、`PriorityBlockingQueue`和`DelayQueue`。 `ArrayBlockingQueue`是一个有界的并发队列,它在创建时...

    Java并发编程相关源码集 包括多任务线程,线程池等.rar

     volatile关键字的非原子性、volatile关键字的使用、AtomicInteger原子性操作、线程安全小例子:多个线程竞争问题、多个线程多个锁问题、创建一个缓存的线程池、多线程使用Vector或者HashTable的示例(简单线程同步...

    Java中使用阻塞队列控制线程集实例

    在这个例子中,使用了`ArrayBlockingQueue`,并且在构造时指定了容量。此外,还可以设置公平性参数,决定线程获取队列元素的策略。如果设置为公平,线程会按照等待时间的长短依次获取元素;非公平模式下,线程获取...

    Java并发工具包java.util.concurrent用户指南中英文对照阅读版pdf

    java.util.concurrent包提供了多种BlockingQueue的实现,包括ArrayBlockingQueue、DelayQueue、LinkedBlockingQueue、PriorityBlockingQueue和SynchronousQueue。每个实现都有其特定的用例和特性,例如...

    Delayed interface and Delay Queue

    3. 创建DelayQueue实例,`DelayQueue&lt;MyDelayedObject&gt; queue = new DelayQueue();` 4. 将延迟对象添加到队列,`queue.put(new MyDelayedObject());` 5. 从队列中获取并处理元素,`MyDelayedObject obj = queue.take...

    基于Redis实现的延迟消息队列

    #### 整体结构 整个延迟队列由4个部分组成: 1. JobPool用来存放所有Job的元信息。 2. DelayBucket是一组以时间为维度的有序队列,用来存放所有需要延迟的Job(这里只存放Job Id)。 3. Timer负责实时扫描各个...

    java线程大总结.pdf

    `BlockingQueue`接口继承自`Queue`接口,提供了多种实现,如`ArrayBlockingQueue`、`DelayQueue`、`LinkedBlockingQueue`、`PriorityBlockingQueue`和`SynchronousQueue`。每个实现都有其特定的特性和使用场景,例如...

    Java集合常见面试题总结(上)-JavaGuide面经思维导图总结

    - 使用延迟队列实现,存储的是`Delayed`接口的实例。 - 特点:只有当延迟到期时才能从队列中取出元素。 #### 三、如何选用集合? 选择合适的集合类型取决于具体的应用场景和需求: - 当需要快速随机访问元素时...

    Java并发编程(21)并发新特性-阻塞队列和阻塞栈(含代

    在这个例子中,生产者线程不断向队列中放入数字,而消费者线程则持续从队列中取出数字,当队列满时,生产者会被阻塞,当队列空时,消费者会被阻塞。这个模型展示了阻塞队列如何有效地协调生产者和消费者的活动。 ...

    Java定时任务

    虽然它们不直接支持定时任务,但可以通过组合使用ScheduledExecutorService和DelayQueue等工具实现定时任务的调度。 在实际应用中,Java定时任务广泛用于数据同步、日志清理、统计分析、系统监控等场景。例如,你...

    java队列之queue用法实例分析

    java队列之queue用法实例分析 java队列之queue用法实例分析主要介绍了java队列之queue用法实例分析,Queue 队列就是一个先入先出(FIFO)的数据结构,Queue接口继承Collection接口。Queue接口与List、Set同一级别,...

    Java延迟队列原理与用法实例详解

    Java延迟队列原理与用法实例详解 Java延迟队列是一种特殊的队列结构,它允许元素在队列中等待一段时间,然后才能被消费。在Java中,延迟队列是通过 DelayQueue 实现的,Delayed 接口定义了延迟队列的元素必须实现的...

    java中线程队列BlockingQueue的用法

    - 消息队列中间件如RabbitMQ、Kafka等在Java客户端API中也广泛使用`BlockingQueue`进行消息传递。 总之,`BlockingQueue`是Java并发编程的重要工具,它通过简单的API实现了复杂的线程同步和协作,是理解和掌握多...

    Java并发编程--BlockingQueue.docx

    示例代码展示了如何创建生产者和消费者线程,它们共享同一个 BlockingQueue 实例,通过 `put()` 和 `take()` 方法实现数据的传递。 在 ArrayBlockingQueue 和 LinkedBlockingQueue 的实现中,当队列满时,生产者...

    高级Java人才培训专家-05-延迟队列精准发布文章

    ### 高级Java人才培训专家-05-延迟队列精准发布文章 #### 知识点解析 **一、文章定时发布的应用场景与需求** - **背景:** 文章定时发布功能适用于多种场景,如新闻更新、博客发布等。该功能允许作者设定文章的...

    Java 阻塞队列详解及简单使用

    下面是一个简单的使用`ArrayBlockingQueue`的例子: ```java import java.util.concurrent.ArrayBlockingQueue; import java.util.concurrent.BlockingQueue; public class BlockingQueueExample { public static...

Global site tag (gtag.js) - Google Analytics