这里有并发问题吗?如何在开发过程中测试它?

时间:2011-02-17 01:48:31

标签: java design-patterns concurrency tdd identity-map

场景:存在'n'个团队,每个团队都在他们的虚拟“墙”上工作(如facebook的墙)。每个团队只看到自己的墙和上面的帖子。这些帖子可以由帖子的作者或其他团队成员编辑(如果这样配置的话。假设确实如此,因为这是必须的)。

设计/技术决策:使用Restlet + Glassfish / Java + Mysql的RESTful Web应用程序(编辑:使用Apache DBUtils进行数据库访问。没有ORM - 似乎有点矫枉过正)

问题:多个团队登录T1,T2和T3(比如说),每个团队都有一些成员。团队级数据访问存在并发性,但团队之间不存在并发性 - 即不同的团队访问不相交的数据集。为了优化对DB的频繁读/写,我们正在考虑一个TeamGateway,它控制对DB的访问以处理并发。 Web服务器将缓存团队检索的数据以加快读取速度(并帮助更新墙上帖子列表)

  • Q1:这是否需要(每个团队的TableGateway +缓存)?如果不是,你怎么建议处理?
  • Q2:如果是这样,TableGateway(每个团队)是否需要编码为线程安全(同步方法)?假设我们有一个类/注册表TableGatewayFinder,它带有一个静态方法,返回TableGateway以用于该特定团队(使用hashmap)。

如果每个T1-T3中有6个人登录,则只会创建3个TableGateways,它是否有助于捕获并发写入(提交前的简单时间戳比较或“冲突标记”附加)并有效管理缓存(我们计划为实体制作身份地图 - 需要跟踪4-5个不同的实体.4个实体用于组合层次结构,另一个实体与4个实体相关联?

一个单元如何测试网关(基于TDD或事后)?

提前致谢!

3 个答案:

答案 0 :(得分:0)

单元测试可能不是并发问题的最佳方法。相反,您可以尝试使用基于Web的性能工具(如JMeter或Rational Performance Tester)来测试它的执行方式,并在增加用户数量时获得有效的墙内容。您可以使用这些工具为每个用户提供不同的发布行为。

答案 1 :(得分:0)

如果您只是在数据库上写入数据库或缓存解决方案(例如Spring + Hibernate + EhCache等),则无需担心损坏表等。从低级别的角度来看,没有并发问题。

如果您想自己编写缓存并自己处理并发问题,那么这将需要一些努力。如果你对缓存进行分片并在每个分区上有一个“全局锁定”(即synchronized在一个公共互斥锁上),并为任何访问获取此锁,那么这将是有效的,而它并不是最高效的方法。但是做一些其他事情而不是全局锁定会涉及很多工作。

虽然这很简单,但不确定为什么要使用身份哈希映射...我想不出你想要做的任何特殊原因(如果你正在考虑性能,那么表现一个在这种情况下,正常的哈希映射是你需要担心的最后一件事!)。

如果您的实体是文章,那么您可能还有其他形式的并发问题。就像SVN,Mercurial等版本控制软件解决的那样。如果你没有把合并功能放到你的应用程序中,如果有人编辑某人的文章只是为了发现其他人已经“提交”了你之前的另一个编辑而变得烦恼。是否你需要添加这样的能力将取决于使用案件。

至于测试您的应用。对于并发性,单元测试也不错。通过编写并发单元测试,捕获并发错误要容易得多。编写并发测试非常困难,因此我建议您在编写之前阅读“Java Concurrency in Practice”等优秀书籍。在集成测试之前更好地捕获并发错误,因为很难猜到到底发生了什么!

<强>更新
@Nupul:这是一个难以回答的问题。但是,如果你只有18个人输入东西,我的赌注是每次写入数据库就好了。

如果你没有在其他地方存储任何状态(即只存在于数据库中),你应该删除任何不必要的互斥锁(除非你有充分的理由这样做,否则你不应该存储除数据库以外的任何其他状态。在你的情况IMO)。

在执行网络操作等操作时很容易出错并获取互斥锁,从而导致极端的可用性问题(例如,应用程序几秒钟内没有响应等)。并且很容易出现令人讨厌的并发错误,如线程死锁等。

所以我的建议是保留你的应用程序。无状态,每次只写DB。如果您发现由于数据库访问导致的任何性能问题,那么转向像EhCache这样的缓存解决方案将是最好的选择。

除非您想从项目中学习或必须提供应用程序。由于性能要求极高,我认为编写自己的缓存层并不合理。

答案 2 :(得分:0)

专注于标题中的2个问题。

  

这里是否存在并发问题?

是。明显。避免并发问题可能性的唯一方法是使产品具有单线程,并且会产生重大性能和可用性问题。

  

如何在开发过程中测试它?

这是个难题。

显然你需要进行单元测试。但是经典的单元测试并没有真正削减它的并发性问题,因为棘手的并发错误往往很少出现。

更好的方法是负载测试。正如@Gnat所述。

但为了获得最佳结果,您需要确认测试不是(整个)解决方案,并添加以下内容:

  • 在设计,编码和测试并发应用程序方面经验丰富的员工。
  • 非常关注Goetz等人的“Java - Concurrency in Practice”的方法/建议。
  • 大量的设计和代码审查。
  • 彻底使用静态代码分析器来解决潜在的并发问题。