是否可以使用JUnit测试多线程?

时间:2011-09-11 08:26:23

标签: java multithreading unit-testing junit

我有一段代码,其中不同的线程操纵HashMap。 我必须同步这段代码。 后来,我想用JUnit测试它。 那么可以使用JUnit测试多线程吗? 如果是的话,请给我一个例子。

2 个答案:

答案 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.");


}