使用JUnit测试多线程代码 - 奇怪的行为

时间:2011-08-06 17:11:53

标签: java multithreading junit io

我是Java的并发新手。我用Junit来测试我的一些代码但结果很奇怪。下面的代码片段在我使用JUnit(Eclipse)运行它时虽然成功执行但没有向控制台写入任何内容。

@Test
public void testGetNameWithMultithreading() { 

    // code to create IndexFile and DictionaryFile...
    ...
    Thread taskOne = new GetNameTask(packOneIndex, packOneDict);
    Thread taskTwo = new GetNameTask(packTwoIndex, packTwoDict);
    taskOne.start();
    taskTwo.start();
}

但是,如果我使用main方法运行,它可以工作:

// Switch to test with good-old main method.
public static void main(String args[]) {

        // code to create IndexFile and DictionaryFile...
        ...
        Thread taskOne = new GetNameTask(packOneIndex, packOneDict);
        Thread taskTwo = new GetNameTask(packTwoIndex, packTwoDict);
        taskOne.start();
        taskTwo.start();
}

这就是任务:

public class GetNameTask extends Thread {

    public GetNameTask (IndexFile indexFile, DictionaryFile dictFile) {
        this.dictFile = dictFile;
        this.indexFile = indexFile;
    }

    @Override
    public void run() {
        Dictionary dictionary = new DICTDictionary(indexFile, dictFile);
        System.out.println(dictionary.getName());
    }

    private final IndexFile indexFile;
    private final DictionaryFile dictFile;
}

构造DICTDictionary时,有一系列IO操作可以从文件中获取字典名称。

使用多线程运行IO代码的任何机会都无法与JUnit一起使用?

编辑:我发现了如何让它发挥作用。因为JUnit在单个线程上执行测试,所以我必须将我的2个小线程连接到JUnit线程以获得预期的结果。所以,这很有效。

@Test
public void testGetNameWithMultithreading() { 

    // code to create IndexFile and DictionaryFile...
    ...
    Thread taskOne = new GetNameTask(packOneIndex, packOneDict);
    Thread taskTwo = new GetNameTask(packTwoIndex, packTwoDict);
    taskOne.start();
    taskTwo.start();
    try {
        taskOne.join();
        taskTwo.join();
    } catch (InteruptedException ie) {
        ie.printStackTrace();
    }
}

有没有更简单的方法来使用JUnit测试多头代码?

最好的问候。

2 个答案:

答案 0 :(得分:2)

您的测试方法必须阻止执行,直到线程完成。

考虑使用ThreadPool。有关详情,请参阅ExecutorService.awaitTemination

答案 1 :(得分:2)

JUnit因未正确处理线程而臭名昭着。

我只能让他们使用TestNG工作。我推荐一个开关。它应该仅仅意味着不同的@Test注释导入和CLASSPATH中的新JAR。