Java多线程工具包java.util.concurrent---DelayQueue

Posted yvan1115

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Java多线程工具包java.util.concurrent---DelayQueue相关的知识,希望对你有一定的参考价值。

延迟队列 DelayQueue

DelayQueue 实现了 BlockingQueue 接口。
DelayQueue 对元素进行持有直到一个特定的延迟到期。
DelayQueue 将会在每个元素的 getDelay() 方法返回的值的时间段之后才释放掉该元素。如果返回的是 0 或者负值,延迟将被认为过期,该元素将会在 DelayQueue 的下一次 take 被调用的时候被释放掉。
传递给 getDelay 方法的 getDelay 实例是一个枚举类型,它表明了将要延迟的时间段。

具体示例

本示例模拟session缓存数据为例。
延迟队列元素
正如你所看到的,Delayed 接口也继承了 java.lang.Comparable 接口,这也就意味着 Delayed 对象之间可以进行对比

class DelayElements implements Delayed 

        private String key;

        // 存活时间
        private long aliveTime;
        // 过期时间
        private long timeOut;

        public long getTimeOut() 
            return timeOut;
        

        public void setTimeOut(long timeOut) 
            this.timeOut = timeOut;
        

        public String getKey() 
            return key;
        

        public void setKey(String key) 
            this.key = key;
        

        public long getAliveTime() 
            return aliveTime;
        

        public void setAliveTime(long aliveTime) 
            this.aliveTime = aliveTime;
        

        public DelayElements(String key, long aliveTime) 
            super();
            this.key = key;
            this.aliveTime = aliveTime;
            this.timeOut = TimeUnit.NANOSECONDS.convert(aliveTime, TimeUnit.SECONDS) + System.nanoTime();
        

        @Override
        public int compareTo(Delayed o) 
            if (o == null)
                return 1;
            if (o == this)
                return 0;
            if (o instanceof DelayElements) 
                DelayElements de = (DelayElements) o;
                if (this.timeOut > de.getTimeOut()) 
                    return 1;
                 else if (this.timeOut < de.getTimeOut()) 
                    return -1;
                
            
            return 0;
        

        @Override
        public long getDelay(TimeUnit unit) 
            return unit.convert(timeOut - System.nanoTime(), TimeUnit.NANOSECONDS);
        

        @Override
        public int hashCode() 
            final int prime = 31;
            int result = 1;
            result = prime * result + ((key == null) ? 0 : key.hashCode());
            return result;
        

        @Override
        public boolean equals(Object obj) 
            if (this == obj)
                return true;
            if (obj == null)
                return false;
            if (getClass() != obj.getClass())
                return false;
            DelayElements other = (DelayElements) obj;
            if (key == null) 
                if (other.key != null)
                    return false;
             else if (!key.equals(other.key))
                return false;
            return true;
        


    

Session类设计

class Session 
        /* 延迟时间,按照秒计算 */
        private static final int _aliveTime = 7;
        /* 延迟队列 */
        DelayQueue<DelayElements> queue = new DelayQueue<>();
        /* 模拟session存放信息,保证线程安全  */
        private ConcurrentHashMap<String, Object> userSession = new ConcurrentHashMap<>();
        public Session() 
        

        public void put(String key, Object value) 
            // 放入session集合中
            userSession.put(key, value);
            // 构造延时列队元素
            DelayElements delayElements = new DelayElements(key, _aliveTime);
            // 移除之前的队列
            queue.remove(key);
            // 插入新的队列
            queue.add(delayElements);
            System.out.println("添加session key:" + key + ",value:" + value.toString() + "成功");
        

        public Object get(String key)
            /*从session池中返回对象*/
            Object resultObject= userSession.get(key);
            if(resultObject!=null)
                /*刷新对应key值的指针,顺延session过期时间*/
                DelayElements delayElements=new DelayElements(key,_aliveTime);
                queue.remove(delayElements);
                queue.put(delayElements);
                System.out.println("获取"+key+"成功:"+resultObject+",生命周期重新计算");
            else
                System.out.println("获取"+key+"失败:"+resultObject+"。对象已过期");
            
            return resultObject;
        

        private void sessionGcMethod() throws InterruptedException
            while(true)
                // 延迟时间内take方法不会获取到值
                // 那么将阻塞线程
                DelayElements delayElements = queue.take();
                queue.remove(delayElements);
                userSession.remove(delayElements.getKey());
                System.out.println("删除过期元素key"+delayElements.getKey());
                Thread.sleep(300);
            
        

        public void startSession()
            Thread seesionGcThread = new Thread(new Runnable() 
                @Override
                public void run() 
                    try 
                        sessionGcMethod();
                     catch (InterruptedException e) 
                        // TODO Auto-generated catch block
                        e.printStackTrace();
                    
                
            );
            // 设置为守护线程
            seesionGcThread.setDaemon(true);
            seesionGcThread.start();
        
    

测试

package com.yvan.DelayQueue;

import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.DelayQueue;
import java.util.concurrent.Delayed;
import java.util.concurrent.TimeUnit;
/**
 * 延时列队
 * @author yvan
 *
 */
public class SessionDelayQueue 

    public static void main(String[] args) throws InterruptedException 
        Session session = new Session();
        session.startSession();
        session.put("username", "yvan");
        Thread.sleep(4000);
        session.put("userlevel", "svip");
        session.get("username");
        Thread.sleep(1000);
        session.get("userlevel");
        Thread.sleep(1000);
        session.get("username");
        Thread.sleep(1000);
        session.get("userlevel");
        Thread.sleep(6000);
        session.get("username");
        Thread.sleep(3000);
        session.get("userlevel");
        Thread.sleep(7000);
        session.get("username");
    

添加session key:username,value:yvan成功
添加session key:userlevel,value:svip成功
获取username成功:yvan,生命周期重新计算
获取userlevel成功:svip,生命周期重新计算
获取username成功:yvan,生命周期重新计算
获取userlevel成功:svip,生命周期重新计算
获取username成功:yvan,生命周期重新计算
删除过期元素keyuserlevel
获取userlevel失败:null。对象已过期
删除过期元素keyusername
获取username失败:null。对象已过期

以上是关于Java多线程工具包java.util.concurrent---DelayQueue的主要内容,如果未能解决你的问题,请参考以下文章

Java多线程工具包java.util.concurrent---CyclicBarrier

Java多线程工具包java.util.concurrent---ExecutorService

Java多线程工具包java.util.concurrent---ReadWriteLock

Java多线程工具包java.util.concurrent---Lock

Java多线程_同步工具CyclicBarrier

Java多线程(线程池原子性并发工具类)