3

我最近必须完成其中一项工作面试编码练习。基本上它需要实现一个消息队列类:

  • 根据传入消息中的优先级字段维护项目。
  • 消息可以是通过 message.priorityField 值范围控制的三个优先级类别之一,高、中、低。
  • 有一个 getSize 和 isEmpty 方法。
  • 有一个 place(message) 方法。
  • 有一个删除方法。
  • 有 getFront() 方法(返回最高优先级的消息)

最后我没有做太多细节的事情是实现一个 MessageQueue 类,该类在内部使用 ConcurrentSkipListMap(并发和有序映射)来保存消息。

我还实现了一个基本的 JUnit 测试用例,用于测试基本的业务需求。

现在,由于它是一个消息队列,因此消息可以同时进入,当然我需要测试实现的发生方面。

我现在越来越接近问题的核心。

我的想法是,当单个线程与实现交互时,基本的 JUnit 测试用例应该验证代码是否有效。

然后我实现了一个并发测试用例,它应该验证实现的发生方面。

现在问题来了:我应该测试哪些并发方面?

我唯一能想到的是有多个生产者线程在队列中注入方法和多个消费者线程删除消息(通过 getFront())。这里要验证的是队列中的任何消息最终都会出来。

但这足够了吗?在这里可以测试哪些其他并发方面?

另外值得注意的是,我已经提交了解决方案,因此无论您提出什么建议,都不会影响我申请这份工作的机会。

4

1 回答 1

2

测试线程安全是一件痛苦的事情,因为您基本上是在尝试为每个最终并发执行证明程序的正确性。有几种方法可以解决这个问题:

  1. 用 JMM 的条款正式证明你的程序的正确性。这将要求您讨论程序中每个明确的“发生前”边缘以及如何基于这些边缘保持一致性。这对于像队列这样基本的东西是可能的,但是随着更多的功能和边缘被抛出,它变得非常复杂。我建议你在任何情况下都经历这个过程,并在编写并发代码时记录你的意图/假设。

  2. 通过使用倒计时锁存器或在程序中的特定点暂停执行线程以强制争用的其他方法,构建演示上述预期行为的测试用例。如果走得太远,这可能会使您的代码变得一团糟,但这可能是一种非常有用的技术。

  3. 通过在足够长的时间内执行代码来统计证明其正确性。这是用于验证关于 JMM 的 JVM 实现正确性的并发折磨套件背后的原理。这将要求您对参与线程的合法/非法状态形成预期,并在具有足够并行线程的机器上运行程序足够长的时间。如果您从未遇到非法状态,那么您的程序是正确的:)。如果您运行它足够长的时间而没有达到非法状态,那么您很可能是正确的。

于 2013-02-04T08:10:49.507 回答