gpt4 book ai didi

java.util.concurrent.DelayQueue 忽略过期元素

转载 作者:塔克拉玛干 更新时间:2023-11-03 04:56:18 24 4
gpt4 key购买 nike

下面的 java 代码示例使用 java DelayQueue 来处理任务。然而,从另一个线程插入任务似乎会破坏(我的)预期行为。

很抱歉代码示例太长,但总而言之:

  1. 主线程将 5 个任务 (A-E) 添加到具有不同延迟(0 毫秒、10 毫秒、100 毫秒、1000 毫秒、10000 毫秒)的延迟队列
  2. 开始另一个步骤,在 3000 毫秒后将另一个任务添加到 DelayQueue
  3. 主线程轮询 DelayQueue 并在每个 Task 到期时报告
  4. 8000 毫秒后,主线程报告延迟队列中剩余的任务

我从代码示例中得到的输出是:

------initial tasks ---------------
task A due in 0ms
task B due in 9ms
task C due in 99ms
task D due in 999ms
task E due in 9999ms
task F due in 99999ms
------processing--------------------
time = 5 task A due in -1ms
time = 14 task B due in 0ms
time = 104 task C due in 0ms
time = 1004 task D due in 0ms
time = 3003 added task Z due in 0ms
------remaining after 15007ms -----------
task F due in 84996ms
task E due in -5003ms
task Z due in -12004ms

我的问题是:为什么在 15000 毫秒后 DelayQueue 中仍然有过期的任务(即 GetDelay() 返回 -ve 值的地方)?

我检查过的一些东西:

  • 我已经实现了 compareTo() 来定义任务的自然顺序
  • equals() 与compareTo() 一致
  • hashCode() 已被覆盖

我最感兴趣的是了解如何解决这个问题。预先感谢您的协助。 (以及所有那些帮助我约会的 Stack Overflow 答案 :)

    package test;

import java.util.concurrent.DelayQueue;
import java.util.concurrent.Delayed;
import java.util.concurrent.TimeUnit;

public class Test10_DelayQueue {

private static final TimeUnit delayUnit = TimeUnit.MILLISECONDS;
private static final TimeUnit ripeUnit = TimeUnit.NANOSECONDS;

static long startTime;

static class Task implements Delayed {
public long ripe;
public String name;
public Task(String name, int delay) {
this.name = name;
ripe = System.nanoTime() + ripeUnit.convert(delay, delayUnit);
}

@Override
public boolean equals(Object obj) {
if (obj instanceof Task) {
return compareTo((Task) obj) == 0;
}
return false;
}

@Override
public int hashCode() {
int hash = 7;
hash = 67 * hash + (int) (this.ripe ^ (this.ripe >>> 32));
hash = 67 * hash + (this.name != null ? this.name.hashCode() : 0);
return hash;
}

@Override
public int compareTo(Delayed delayed) {
if (delayed instanceof Task) {
Task that = (Task) delayed;
return (int) (this.ripe - that.ripe);
}
throw new UnsupportedOperationException();
}

@Override
public long getDelay(TimeUnit unit) {
return unit.convert(ripe - System.nanoTime(), ripeUnit);
}

@Override
public String toString() {
return "task " + name + " due in " + String.valueOf(getDelay(delayUnit) + "ms");
}
}

static class TaskAdder implements Runnable {

DelayQueue dq;
int delay;

public TaskAdder(DelayQueue dq, int delay) {
this.dq = dq;
this.delay = delay;
}

@Override
public void run() {
try {
Thread.sleep(delay);

Task z = new Task("Z", 0);
dq.add(z);

Long elapsed = System.currentTimeMillis() - startTime;

System.out.println("time = " + elapsed + "\tadded " + z);

} catch (InterruptedException e) {
}
}
}

public static void main(String[] args) {
startTime = System.currentTimeMillis();
DelayQueue<Task> taskQ = new DelayQueue<Task>();

Thread thread = new Thread(new TaskAdder(taskQ, 3000));
thread.start();

taskQ.add(new Task("A", 0));
taskQ.add(new Task("B", 10));
taskQ.add(new Task("C", 100));
taskQ.add(new Task("D", 1000));
taskQ.add(new Task("E", 10000));
taskQ.add(new Task("F", 100000));

System.out.println("------initial tasks ---------------");
Task[] tasks = taskQ.toArray(new Task[0]);
for (int i = 0; i < tasks.length; i++) {
System.out.println(tasks[i]);
}

System.out.println("------processing--------------------");
try {
Long elapsed = System.currentTimeMillis() - startTime;
while (elapsed < 15000) {
Task task = taskQ.poll(1, TimeUnit.SECONDS);
elapsed = System.currentTimeMillis() - startTime;
if (task != null) {
System.out.println("time = " + elapsed + "\t" + task);
}
}

System.out.println("------remaining after " + elapsed + "ms -----------");
tasks = taskQ.toArray(new Task[0]);
for (int i = 0; i < tasks.length; i++) {
System.out.println(tasks[i]);
}

} catch (InterruptedException e) {
}
}
}

最佳答案

因为您的comapareTo 方法充满缺陷。正确的实现如下。一旦你像下面这样改变,你所有的问题都会得到解决。如果或遵守 compareTo Contract

,请始终尝试重用 compareTo 方法
return Long.valueOf(this.ripe).compareTo(that.ripe);

关于java.util.concurrent.DelayQueue 忽略过期元素,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/12142025/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com