【问题标题】:Command pattern queue ordered by time?命令模式队列按时间排序?
【发布时间】:2012-04-30 11:02:36
【问题描述】:

我正在更改一些代码以使用命令模式并将命令对象存储在队列中。这些命令需要在特定时间执行,因此我将每秒遍历列表一次以查找要执行的命令。

每个命令对象都会有一个时间,我会根​​据当前时间检查这个时间(在一个小阈值内)。因此,如果时间匹配,我需要从列表中删除命令对象,然后执行它。通常在任何给定时间都会有不到 10 个命令。我应该使用什么集合数据结构以及如何在迭代列表时删除命令对象?

【问题讨论】:

    标签: c++ queue command-pattern


    【解决方案1】:

    我想你想使用priority queue。这是一个容器,可让您拉取最高优先级的项目。在您的情况下,“更高优先级”是“首先发生”。

    C++ 将优先级队列建模为priority_queue 容器适配器。这意味着它内部还有一些其他容器可以进行实际存储。这个容器通常是vectordeque。 (需要随机访问迭代器。)默认为vector。所以你可以声明:

    std::priority_queue<T, vector<T>, Compare> queue;
    

    其中T 是您的元素,Compare 是一个比较两个T 元素的函数,如果第一个元素的优先级低于第二个元素,则返回true。如果您为您的类型T 定义了operator &lt;,它会变得更加简单:

    std::priority_queue<T> queue;
    
    • 将项目放入队列:queue.push(item);
    • 获取最高优先级元素:queue.top()
    • 要删除队列的顶部项目:queue.pop();

    注意pop() 不会返回被移除的元素;它只是删除和破坏它。

    【讨论】:

    • 所以我想这将涉及使用时间作为优先级?由于我需要在一天中的特定时间(例如上午 11:27:19)运行命令,我是否会一直弹出命令,直到弹出一个超过当前时间的命令,然后将该命令放回队列中?跨度>
    • 不,只要您的 Compare 函数有效,优先级队列就会为您安排好事情。所以当你抓住top() 时,你知道它是最高优先级的项目。只要确保Compare(a, b)a &lt; b 返回true 如果b 出现在a 之前。所以你只看top(),执行它与否,如果你执行它,只有pop()它。无需重新插入。
    • 请注意,&lt; 对于时间的通常定义将不起作用,因为它将较早定义为“小于”较晚。因此,您可能只想为您的班级 T 定义自己的 &lt;
    • 啊,我明白了。您觉得这与遍历向量(因为列表会很小)相比如何?
    • @user 因为列表非常小,你可以使用任何你想要的数据结构。这是为了您的方便!例如,如果您要按执行顺序列出待处理的命令,那么您必须使用纯向量对它们进行排序。使用我在下面发布的priority_queuemap/multimap 解决方案,您就可以开始了。您可以密切关注单个项目 - 结构顶部的一个以决定是否必须执行任何命令。无需迭代。
    【解决方案2】:

    Mike 的解决方案的替代方案是使用有序映射,在 STL 的情况下它只是一个 map。您可以将时间作为键,将命令作为值。根据您的情况,它可能比排队更方便。

    如果允许同时执行两个命令,那么你应该使用multimap

    multimap<time_t, Command> schedule;
    
    schedule.insert(pair<time_t, Command>(123456, formatHDDCommand));
    

    【讨论】:

    • 基于地图的解决方案的问题是我需要允许一点滑动,所以如果当前时间比目标时间晚 1 或 2 秒并且命令仍未执行,我仍然需要它执行。
    • @User 当然!您不应该在地图上搜索确切的时间。相反,您还有另外两条途径可以利用多图。首先,您可以选择beginend(取决于时间表示)迭代器并将其时间与当前时间进行比较。如果当前时间较大,则执行该命令。根据需要重复此步骤。其次,您可以使用find() 函数以当前时间作为参数,并从find() 返回的迭代器开始迭代。 find() 将“切断”命令,这个时间还没有到来。
    • 啊,我明白了,我以为你在建议一个精确的键匹配,但你正在使用地图,因为它是有序属性
    • 不要使用end();根据定义,它不指向有效元素。请改用rbegin()。此外,根据问题的定义,您不需要使用find()。你会 。总的来说,这是一个比priority_queue 复杂得多的解决方案,而且你真的不需要map 的O(logN) 搜索时间功能。您不是在进行任意搜索;您的所有工作都将与最早的事件一起进行,因为您希望按顺序处理它们。
    • @MikeDeSimone 我也更喜欢你的priority_queue。但我推测在某些情况下,map/multimap 会更方便。也许执行时间将绑定到其他数据结构或预测?然后快速查找精确的键 => 值对是有意义的并且是合理的。此外,时间粒度可能大到足以证明多图的合理性。例如,在人类尺度上,如果时间以小时表示,那么要求在指定时间执行命令是有意义的,而 multimap 似乎是自然的选择。这是人类的尺度,但在较小的尺度上也是如此。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-11-23
    • 2015-06-30
    • 1970-01-01
    • 1970-01-01
    • 2013-08-06
    • 2015-04-10
    相关资源
    最近更新 更多