我最近不得不完成其中一个面试编码练习。基本上,它需要实现一个消息队列类:
我最后没有详细介绍的是实现一个MessageQueue类,它在内部使用ConcurrentSkipListMap(一个并发和有序的映射)来保存消息。
我还实现了一个基本的JUnit测试用例,用于测试基本的业务需求。
现在,由于它是一个消息传递队列,因此消息可以同时出现,我需要测试实现的当前方面。
我现在越来越接近问题的核心。
我的想法是,当单个线程与实现交互时,基本的JUnit测试用例应验证代码是否有效。
然后我实现了一个并发测试用例,该测试用例应该验证实现的当前方面。
现在问题是: 我应该测试哪些并发方面?
我唯一能想到的是让多个生产者线程在队列中注入方法,以及多个消费者线程来删除消息(通过getFront())。 这里验证的是,队列中的任何消息最终都会出现。
但那够了吗?在这里可以测试哪些其他并发方面?
另外值得注意的是,我已经提交了解决方案,所以无论你提出什么建议都不会影响我申请这份工作的机会。
答案 0 :(得分:2)
测试线程安全是一件很痛苦的事情,因为您基本上都在尝试为每个最终的并发执行证明程序的正确性。有几种方法可以解决这个问题:
以JMM的形式正式证明您的计划的正确性。这将要求您讨论程序中每个明确的“先发生”边缘以及如何基于这些边缘保持一致性。这对于像队列这样基本的东西是可能的,但是变得非常复杂,更多的功能和边缘被抛入。我建议你在任何情况下都要经历这个过程,并在编写并发代码时记录你的意图/假设。
通过使用倒计时锁存器或其他方法在程序中的特定点暂停执行线程来强制争用,从而构建用于演示上述行为的测试用例。如果采取太长的措施,这可能会使你的代码陷入可怕的混乱,但这可能是一种非常有用的技术。
通过在足够长的时间内执行代码来统计证明正确性。这是concurrency torture suite背后的原理,用于验证JVM的JVM实现正确性。这将要求您对参与线程的合法/非法状态形成期望,并在具有足够并行线程的计算机上运行您的程序足够长的时间。如果你从未打过非法状态你的程序是正确的:)。如果你运行它的时间足够长而没有达到非法状态,那么你很可能是正确的。