我有一段代码,其中不同的线程操纵HashMap。 我必须同步这段代码。 后来,我想用JUnit测试它。 那么可以使用JUnit测试多线程吗? 如果是的话,请给我一个例子。
答案 0 :(得分:2)
当然,但这并不容易。
Freeman& amp; Pryce的"Growing Object Oriented Software"书,我强烈推荐。
答案 1 :(得分:2)
我实际上是这样做的,但仅适用于简单的多线程场景。基本上,您想要的是将多个线程的访问同步到您的hashmap,或者换句话说,具有可预测的顺序,其中一堆线程到哈希映射上的东西。您可以构建测试用例,其中每个Thread都会在nanime中记录,并且每次执行某些操作时都会有一些唯一的id,然后在这些日志条目上有一个断言(可以保存在memroy中,它们不必输出到实际文件)检查它们是否按正确的顺序。
以下是我如何对多个(实际上只是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.");
}