需求场景描述:
C/S结构的程序. 客户端监听服务器端发来的信息,并向用户报告. 内容相同的信息,服务器端可能会重复发送3到5次, 每次间隔0.01秒. 用户希望, 对于这些重复发送的信息, 只报告一次即可.
分析:
这里面有几个关键的问题:
首先,
如何判断当前的消息是否是重复消息. 可以通过保存一个消息列表来实现.
这里有两种实现方法: 1, 保证消息列表是绝对最新的, 这样,新消息到来的时候只要判断列表中是否存在即可. 2, 不保证列表是绝对最新, 新消息来的时候除了判断内容,还要判断时间. 这两种方案其实是在“实时维护列表的严格最新”和“搜索时的进行比较的条件和次数”两件事情之间的权衡.
由此引发第二个问题:
列表更新的时机。列表有必要在任何时刻都是严格最新的吗?显然没有。即使需要最新,也只要在搜索列表之前保证是最新的就可以了。所以,无论是扫描线程,还是计时器,虽然严格符合了程序的要求,但是不必要的。因此,我们可以给出几个更新的时机,比如,每隔固定时间进行更新,有消息到达时进行更新,或消息数量到达某一上限时进行更新,在其中权衡。(酷似内存管理中的“快表淘汰算法”)
权衡下来,对于第一个问题,对列表的遍历和维护的开销要大于增加一个比较条件的开销。对于第二个问题,我们选择了在消息数量达到某个阈值时进行更新。如下4个方案,展示了对以上两个关键问题逐步改善的过程。
方案1:
把收到的信息保存起来, 每当新来一个信息, 和保存的消息比较, 如果消息列表中存在某个消息和当前消息内容相等(
无需比较时间
.
因为列表中的消息一定是最新的), 则丢弃该消息. 否则,向用户报告该消息, 并加入消息列表. 消息列表中的每条消息都附加一个计时器. 到0.05秒后自行离开消息列表.
方案2:
筛选消息的方法和方案1相同. 和方案1的差别是, 无需给每个消息都附加计时器. 而是另外启动一个监视线程, 每隔0.01秒扫描消息列表, 删除时间戳和当前时间之差超过0.05秒的消息.
方案3:
把收到的信息保存起来, 每当新来一个信息, 首先扫描消息列表, 删除时间戳和当前时间之差超过0.05秒的消息. 然后查找消息列表, 如果消息列表中存在某个消息和当前消息内容相等,
(
无需检查时间戳
.
因为列表中的过期的消息已经被删除
), 则丢弃该消息. 否则,向用户报告该消息, 并加入消息列表.
方案4:
每当新来一个信息, 查找消息列表. 如果消息列表中存在某个消息和当前消息内容相等,
并且时间戳之差小于
0.05
秒
(
因为列表中的消息不一定是最新的
), 则丢弃该消息. 否则,向用户报告该消息, 并加入消息列表. 另外, 不使用监视线程来扫描消息列表. 而是规定一个阈值, 每当消息列表中的消息数量超过这个阈值的时候, 扫描消息列表, 删除时间戳和当前时间之差超过0.05秒的消息.