【问题标题】:Time-based thread-safe priority queue基于时间的线程安全优先级队列
【发布时间】:2016-02-01 09:18:00
【问题描述】:

我需要一些类似队列的数据结构来完成以下任务:

  1. 某些线程添加了附加延迟值(例如以秒为单位)的数据项,例如queue.add(data, delay)
  2. 可以有不同的延迟,也可以是相同的,队列应该作为优先队列:延迟越小越接近尾端(出队更快)
  3. 每秒delay 排队的项目应该减少 1 直到它达到 0(然后它将保持不变为 0)
  4. delay0 的项目中,出队的顺序就是它们的插入顺序(尽管到达0 的顺序更好)
  5. 一些客户端线程系统地从这个队列中获取元素,它只给出delay = 0 元素。如果不存在,则它会阻塞或抛出。

因此,我想要一些队列功能 + 一点调度,线程安全。我怀疑这种事情在某些情况下应该是相当常规的任务。

我的问题:对于此类任务,javascala 是否有任何生产就绪解决方案?我不想重新发明另一辆自行车。

编辑java标准库中似乎有确切的这样的东西:DelayQueue,在回答之前先看看它。

【问题讨论】:

  • 与其每秒修改所有项目的delay,不如在它们准备好出列时存储时间戳。队列的顺序不会因此而改变,并且可以省去更新工作。
  • @Henry 这确实是合理的。
  • 你看过 ScheduledThreadPoolExecutor 了吗?
  • 听起来您真的应该使用 ScheduledThreadPoolExecutor,因为这将延迟的 PriorityQueue 和 ThreadPool 封装在一个中。
  • 实际上,可以添加一个 ScheduledThreadPoolExecutor 作为中间步骤;当达到延迟 = 0 时,它会将其添加到另一个队列中,该队列将立即可供轮询;但是无论如何你都需要第二个队列(但这次不一定是 PriorityQueue)。

标签: java scala data-structures scheduling


【解决方案1】:

您可以使用PriorityQueue 作为输入Comparable 对象。 您应该根据Timestamp 字段比较这些对象(越小越好);正如@Henry 已经提到的,最好存储Timestamp 而不是delay。这很容易实现;只需存储currentTime + delay

然后,当客户端请求 head 元素时,您需要创建一个 synchronized 方法,该方法执行以下操作:

  • 首先peek()检查头部元素是否有timestamp < currentTime
  • 如果是,poll() 这个元素,否则抛出。

第二个解决方案(来自我的评论):

实际上,可以添加一个 ScheduledThreadPoolExecutor 作为中间层; 现在您不需要Timestamp,只需将delay 提供给执行者即可。

当每个runnable/callable执行时,对应的对象会被添加到另一个普通的FIFO Queue中,在那里它会立即可供轮询;

您的客户现在可以从第二个 FIFO 队列中轮询元素。

【讨论】:

  • 使用了您最初的建议,这确实是微不足道的。谢谢。
猜你喜欢
  • 1970-01-01
  • 2014-04-07
  • 1970-01-01
  • 2020-01-29
  • 2021-07-28
  • 2016-09-23
  • 1970-01-01
  • 1970-01-01
  • 2021-12-20
相关资源
最近更新 更多