3位游泳者同时进行游泳馆,各自游泳时间分别是 1 分钟,2 分钟,3 分钟,按规定到了结束时间后游泳者自动离开。请用队列模拟以上场景。
package concurrent.swim;
import java.util.concurrent.Delayed;
import java.util.concurrent.TimeUnit;
/**
* @className: Swimmer
* @description: 游泳者
* @date: 2022/3/21
* @author: cakin
*/
public class Swimmer implements Delayed {
// 姓名
private String name;
// 结束时间
private long endTime;
public Swimmer() {
}
public Swimmer(String name, long endTime) {
this.name = name;
this.endTime = endTime;
}
public String getName() {
return this.name;
}
/*
是否还有剩余时间。
如果返回正数,表明还有剩余时间;
如果返回0或者负数,说明已超时;超时时,才会让 DelayQueue 的 take() 方法真正取出元素。
*/
@Override
public long getDelay(TimeUnit unit) {
return endTime - System.currentTimeMillis();
}
// 线程(游泳者)之间,根据剩余时间的大小进行排序
@Override
public int compareTo(Delayed delayed) {
Swimmer swimmer = (Swimmer) delayed;
return this.getDelay(TimeUnit.SECONDS) - swimmer.getDelay(TimeUnit.SECONDS) > 0 ? 1 : 0;
}
}
package concurrent.swim;
import java.util.concurrent.DelayQueue;
/**
* @className: Natatorium
* @description: 游泳馆
* @date: 2022/3/21
* @author: cakin
*/
public class Natatorium implements Runnable {
// 用延迟队列模拟多个Swimmer,每个 Swimmer 的 getDelay() 方法就表示自己剩余的游泳时间
private DelayQueue<Swimmer> queue = new DelayQueue<>();
// 标识游泳馆是否开业
private volatile boolean isOpen = true;
/**
* 功能描述:向 DelayQueue中 增加游泳者
*
* @param name 游泳者名字
* @param playTime 游泳者时长
* @author cakin
* @date 2022/3/21
*/
public void addSwimmer(String name, int playTime) {
// 规定游泳的结束时间
long endTime = System.currentTimeMillis() + playTime * 1000 * 60;
Swimmer swimmer = new Swimmer(name, endTime);
System.out.println(swimmer.getName() + "进入游泳馆,可供游泳时间:" + playTime + "分");
this.queue.add(swimmer);
}
@Override
public void run() {
while (isOpen) {
try {
/*
* 注意:在 DelayQueue 中,take() 并不会立刻取出元素。
* 只有当元素(Swimmer)所重写的 getDelay() 返回0或者负数时,才会真正取出该元素。
*/
Swimmer swimmer = queue.take();
System.out.println(swimmer.getName() + "游泳时间结束");
// 如果 DelayQueue中 的元素已被取完,则停止线程
if (queue.size() == 0) {
isOpen = false;
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
package concurrent.swim;
/**
* @className: TestNatatorium
* @description: 游泳馆测试类
* @date: 2022/3/21
* @author: cakin
*/
public class TestNatatorium {
public static void main(String args[]) {
try {
Natatorium natatorium = new Natatorium();
Thread nataThread = new Thread(natatorium);
nataThread.start();
natatorium.addSwimmer("zs", 1);
natatorium.addSwimmer("ls", 2);
natatorium.addSwimmer("ww", 3);
} catch (Exception e) {
e.printStackTrace();
}
}
}
zs进入游泳馆,可供游泳时间:1分
ls进入游泳馆,可供游泳时间:2分
ww进入游泳馆,可供游泳时间:3分
zs游泳时间结束
ls游泳时间结束
ww游泳时间结束
该案例是用延迟阻塞队列解决问题,当 3 位游泳者时间结束时,就会陆续收到提示。
版权说明 : 本文为转载文章, 版权归原作者所有 版权申明
原文链接 : https://blog.csdn.net/chengqiuming/article/details/123643016
内容来源于网络,如有侵权,请联系作者删除!