【发布时间】:2011-09-11 08:26:23
【问题描述】:
我有一段代码,其中不同的线程操作 HashMap。 我必须同步这段代码。 稍后,我想使用 JUnit 对此进行测试。 那么是否可以使用 JUnit 测试多线程? 如果可以,请给我一个例子。
【问题讨论】:
标签: java multithreading unit-testing junit
我有一段代码,其中不同的线程操作 HashMap。 我必须同步这段代码。 稍后,我想使用 JUnit 对此进行测试。 那么是否可以使用 JUnit 测试多线程? 如果可以,请给我一个例子。
【问题讨论】:
标签: java multithreading unit-testing junit
当然,但这并不容易。
Freeman & Pryce 的 "Growing Object Oriented Software" 书中有一个关于这个主题的精彩章节,我强烈推荐。
【讨论】:
我实际上已经这样做了,但仅适用于简单的多线程场景。基本上,您想要的是同步多个线程对您的 hashmap 的访问,或者换句话说,有一个可预测的顺序,其中一堆线程到 hash map 上的事物。您可以构建测试用例,其中每个线程在每次执行某些操作时都记录在纳米时间和一些唯一的 id,然后对这些日志条目进行断言(可以保存在内存中,它们不必输出到实际文件)检查它们的顺序是否正确。
这是我如何对访问数据库的多个(实际上只有 2 个)线程进行单元测试的示例,以确保它们按照我期望的顺序执行:
@Test
public void testPessimisticLock3_write_blocking() throws Throwable {
init();
final ArrayList<String> eventsOrder = new ArrayList<String>();
Department d = new Department();
d.setName("d");
em.getTransaction().begin();
em.persist(d);
em.getTransaction().commit();
id=d.getId();
em.getTransaction().begin();
//aquire lock:
@SuppressWarnings("unused")
Department dRet1 = em.find(Department.class, d.getId(),LockModeType.PESSIMISTIC_WRITE);
eventsOrder.add("First transaction got the lock");
// dRet1.setName("dRet1");
eventsOrder.add("First transaction will sleep for a while...");
Thread.sleep(1500);
new Thread(new Runnable() {
@Override
public void run() {
em2.getTransaction().begin();
//this will wait for the first transaction to release the lock, so that this 2nd transaction can acquire the lock
eventsOrder.add("Second transaction will now try to get the lock...");
em2.find(Department.class, id,LockModeType.PESSIMISTIC_WRITE);
eventsOrder.add("Second transaction got the lock.");
em2.getTransaction().commit();
assertEquals("First transaction got the lock",eventsOrder.get(0));
assertEquals("First transaction will sleep for a while...",eventsOrder.get(1));
assertEquals("Second transaction will now try to get the lock...",eventsOrder.get(2));
assertEquals("First transaction woke up and will commit...",eventsOrder.get(3));
assertEquals("First transaction has commited.",eventsOrder.get(4));
assertEquals("Second transaction got the lock.",eventsOrder.get(5));
}
}).start();
Thread.sleep(1500);
eventsOrder.add("First transaction woke up and will commit...");
em.getTransaction().commit();
eventsOrder.add("First transaction has commited.");
}
【讨论】: