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