一个支持延时获取元素的无界阻塞队列
案例:
模拟一个网吧,网民上网,充值,到时间后下机的情景,是怎么利用Queue的
1.网民实体类
package com.gao.test.internetcafe;
import java.math.BigDecimal;
import java.util.concurrent.Delayed;
import java.util.concurrent.TimeUnit;
/**
* 网名实体类
*/
public class Netizen implements Delayed {
//网民的身份证
private String idNo;
//网民的姓名
private String netizenName;
//上网时剩余金额
private BigDecimal netMoney;
//上网剩余时间
private long playTime;
//有参构造函数
public Netizen(String idNo, String netizenName, long playTime) {
this.idNo = idNo;
this.netizenName = netizenName;
this.playTime = playTime;
}
/**
* 此方法是用来判断你的元素的延迟时间是到期
* 获取能上网的时长
*/
@Override
public long getDelay(TimeUnit unit) {
//时长=上网截止的时间-当前时间
return this.playTime - System.currentTimeMillis();
}
/**
* 比较优先级,时间最短的优先
* 此方法是根据延迟时间从小到大来排列到队列中的元素
* @param o
* @return
*/
@Override
public int compareTo(Delayed o) {
Netizen n = (Netizen) o;
return this.getDelay(TimeUnit.SECONDS)-o.getDelay(TimeUnit.SECONDS)>0?1:0;
}
//网民姓名的get方法
public String getNetizenName() {
return netizenName;
}
}
2.网吧类
package com.gao.test.internetcafe;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.concurrent.DelayQueue;
/**
* 网吧类
*/
public class InternetCafe implements Runnable{
//上网钱和时间的比率(1元=多少秒),这里取 1元/10秒
private static final long MONEY_TIME_RATIO = 1000*10;
//上网人的队列,使用延时阻塞队列
private DelayQueue<Netizen> dq = new DelayQueue<>();
//给时间格式化
SimpleDateFormat sbf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
//上网的方法
public void playGame(String idNo, String name, double netMoney){
//截止时间=钱数*时间(1元对应多少时间)+当前时间
Netizen netizen = new Netizen(idNo,name,new Double(netMoney).longValue()*MONEY_TIME_RATIO+System.currentTimeMillis() );
System.out.println("欢迎光临,"+name +",于"+sbf.format(new Date())+"开始上网计费...");
//把网民加入到队列中
dq.add(netizen);
}
//下机的方法
public void playOver(Netizen netizen){
System.out.println(netizen.getNetizenName() + ":您好,"+sbf.format(new Date())+ "上网时间已到,请下机或者续费...");
}
/**
* 覆写线程方法
*/
@Override
public void run() {
//监控每个网民的上网时长
while (true) {
try {
//取出并移除网民,take取出元素并移除,没有元素会阻塞
Netizen netizen = dq.take();
//运行下机方法
playOver(netizen);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
3.上网管理
package com.gao.test.internetcafe;
/**
* 模拟网吧管理
*/
public class InterentCafeManage {
public static void main(String[] args) {
//创建网吧
InternetCafe internetCafe = new InternetCafe();
//添加上网的人(身份id,姓名,钱数)
internetCafe.playGame("001","张三",3.00);
internetCafe.playGame("002","李四",8.00);
internetCafe.playGame("003","王五",10.00);
Thread t1 = new Thread(internetCafe);
t1.start();
}
}