在JUC中提供自动弹出数据的延迟队列DelayQueue,该类属于BlockingQueue接口子类,而对于延迟操作的计算则需要通过Delayed接口进行计算。
1、使用延迟队列(模拟讨论会一次离开的场景)的例子:
package com.mydemo;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.DelayQueue;
import java.util.concurrent.Delayed;
import java.util.concurrent.TimeUnit;
public class JUCDemo {
public static void main(String[] args) throws InterruptedException {
// 定义延迟队列
BlockingQueue<Student> blockingQueue = new DelayQueue<>();
// 保存队列延迟信息
blockingQueue.put(new Student("小明", 2, TimeUnit.SECONDS));
blockingQueue.put(new Student("小华", 5, TimeUnit.SECONDS));
blockingQueue.put(new Student("小红", 10, TimeUnit.SECONDS));
// 是否还有人在
while (!blockingQueue.isEmpty()){
// 获取弹出数据
Student student = blockingQueue.take();
System.out.println(student);
// 延迟操作
TimeUnit.SECONDS.sleep(1);
}
}
}
// 定义延迟计算
class Student implements Delayed {
private String name; // 姓名
private long delay; // 停留时间
private long expire; // 离开时间
public Student(String name, long delay, TimeUnit timeUnit) {
this.name = name;
// 失效时间计算
// 如果要计算离开时间,肯定需要与当前系统时间进行比较,系统时间返回的都是毫秒
this.delay = TimeUnit.MILLISECONDS.convert(delay, timeUnit);
this.expire = System.currentTimeMillis() + this.delay;
}
@Override
public String toString() {
return this.name + "同学已经到了预计的停留时间“"
+ TimeUnit.SECONDS.convert(this.delay, TimeUnit.MILLISECONDS)
+ "”秒,已经离开了。";
}
/**
* 延迟时间计算
* @param unit
* @return
*/
@Override
public long getDelay(TimeUnit unit) {
return unit.convert(this.expire - System.currentTimeMillis(), TimeUnit.MILLISECONDS);
}
/**
* 队列弹出计算
* @param o
* @return
*/
@Override
public int compareTo(Delayed o) {
return (int)(this.delay - this.getDelay((TimeUnit.MILLISECONDS)));
}
}
运行结果:
小明同学已经到了预计的停留时间“2”秒,已经离开了。
小华同学已经到了预计的停留时间“5”秒,已经离开了。
小红同学已经到了预计的停留时间“10”秒,已经离开了。
2、实现缓存操作的例子:
package com.mydemo;
import java.util.Map;
import java.util.concurrent.*;
public class JUCDemo {
public static void main(String[] args) throws Exception {
// 定义缓存类对象
Cache<Long, News> cache = new Cache<>();
// 向缓存保存数据
cache.put(1l, new News(1L, "新闻标题1"));
cache.put(2l, new News(2L, "新闻标题2"));
cache.put(3l, new News(3L, "新闻标题3"));
// 通过缓存获取数据
System.out.println("缓存数据1l : " + cache.get(1l));
System.out.println("缓存数据2l : " + cache.get(2l));
System.out.println("缓存数据3l : " + cache.get(3l));
// 延迟获取---设置的是2秒自动删除,所以5秒后没数据了
TimeUnit.SECONDS.sleep(5);
System.out.println("==============================");
// 通过缓存获取数据
System.out.println("缓存数据3l : " + cache.get(3l));
}
}
// 定义一个缓存数据处理类
class Cache<K, V>{
private static final TimeUnit TIME = TimeUnit.SECONDS; // 时间工具类
private static final long DELAY_SECONDES = 2; // 缓存时间
private Map<K, V> cacheObjects = new ConcurrentHashMap<>(); // 设置缓存集合
// 启动守护线程
private BlockingQueue<DelayedItem<Pair>> blockingQueue = new DelayQueue<>();
/**
* 无参构造
*/
public Cache() {
Thread thread = new Thread(()->{
while (true){
try {
// 数据消费
DelayedItem<Pair> delayedItem = Cache.this.blockingQueue.take();
// 有数据
if(delayedItem != null){
// 获取数据
Pair pair = delayedItem.getItem();
// 删除数据
Cache.this.cacheObjects.remove(pair.key, pair.value);
}
}catch (Exception e){}
}
});
// 设置后台线程
thread.setDaemon(true);
// 线程启动
thread.start();
}
/**
* 保存数据
* @param key
* @param value
*/
public void put(K key, V value) throws Exception {
// 数据保存
V oldValue = this.cacheObjects.put(key, value);
// 重复保存
if (oldValue != null) {
// 删除已有的数据
this.blockingQueue.remove(oldValue);
}
this.blockingQueue.put(new DelayedItem<Pair>(new Pair(key, value), DELAY_SECONDES, TIME));
}
/**
* 获取缓存数据
* @param key
* @return
*/
public V get(K key){
// Map查询
return this.cacheObjects.get(key);
}
// 封装保存数据
private class Pair{
private K key; // 数据key
private V value; // 数据value
/**
* 双参构造函数---数据value
* @param key
* @param value
*/
public Pair(K key, V value) {
this.key = key;
this.value = value;
}
}
private class DelayedItem<T> implements Delayed {
private T item; // 数据项
private long delay; // 保存时间
private long expire; // 失效时间
/**
* 三参构造
* @param item
* @param delay
* @param timeUnit
*/
public DelayedItem(T item, long delay, TimeUnit timeUnit) {
this.item = item;
this.delay = TimeUnit.MILLISECONDS.convert(delay, timeUnit);
this.expire = System.currentTimeMillis() + this.delay;
}
/**
* 延时计算
* @param unit
* @return
*/
@Override
public long getDelay(TimeUnit unit) {
return unit.convert(this.expire - System.currentTimeMillis(), TimeUnit.MILLISECONDS);
}
@Override
public int compareTo(Delayed o) {
return (int)(this.delay - this.getDelay(TimeUnit.MILLISECONDS));
}
public T getItem() {
return item;
}
public void setItem(T item) {
this.item = item;
}
}
}
// 新闻数据
class News{
private long nid;
private String title;
public News(long nid, String title) {
this.nid = nid;
this.title = title;
}
@Override
public String toString() {
return "News{" +
"新闻编号:" + this.nid +
", 新闻标题:" + this.title + '\'' +
'}';
}
}
运行结果:
缓存数据1l : News{新闻编号:1, 新闻标题:新闻标题1'}
缓存数据2l : News{新闻编号:2, 新闻标题:新闻标题2'}
缓存数据3l : News{新闻编号:3, 新闻标题:新闻标题3'}
==============================
缓存数据3l : null