JUnit 学习笔记

JUnit4 测试多线程

2017-01-24  本文已影响75人  专职跑龙套

JUnit4 实际上不支持测试多线程程序。

The article at http://www.planetgeek.ch/2009/08/25/how-to-find-a-concurrency-bug-with-java/describes a method of exposing concurrency bugs that adds a new assertion method assertConcurrent.

该文章中提供了一个新的断言方法来测试多线程程序:
assertConcurrent(final String message, final List<? extends Runnable> runnables, final int maxTimeoutSeconds)

该方法将需要测试的线程放入一个线程池中,并发执行,最后判断是否有异常发生,是否有超时发生。

示例如下:
如下的代码会产生超时,测试不通过。
java.lang.AssertionError: Test Failed timeout! More than1seconds

public class JUnit4_Test {
    @Test
    public void test1() throws Exception {
        List<Runnable> runnables = new ArrayList<>(10);
        for (int i = 0; i < 10; i++) {
            runnables.add(new MyRunnable());
        }

        assertConcurrent("Test Failed", runnables, 1);
    }

    public static void assertConcurrent(final String message, final List<? extends Runnable> runnables, final int maxTimeoutSeconds) throws InterruptedException {
        final int numThreads = runnables.size();
        final List<Throwable> exceptions = Collections.synchronizedList(new ArrayList<Throwable>());
        final ExecutorService threadPool = Executors.newFixedThreadPool(numThreads);
        try {
            final CountDownLatch allExecutorThreadsReady = new CountDownLatch(numThreads);
            final CountDownLatch afterInitBlocker = new CountDownLatch(1);
            final CountDownLatch allDone = new CountDownLatch(numThreads);
            for (final Runnable submittedTestRunnable : runnables) {
                threadPool.submit(new Runnable() {
                    public void run() {
                        allExecutorThreadsReady.countDown();
                        try {
                            afterInitBlocker.await();
                            submittedTestRunnable.run();
                        } catch (final Throwable e) {
                            exceptions.add(e);
                        } finally {
                            allDone.countDown();
                        }
                    }
                });
            }
            // wait until all threads are ready
            assertTrue("Timeout initializing threads! Perform long lasting initializations before passing runnables to assertConcurrent", allExecutorThreadsReady.await(runnables.size() * 10, TimeUnit.MILLISECONDS));
            // start all test runners
            afterInitBlocker.countDown();
            assertTrue(message + " timeout! More than" + maxTimeoutSeconds + "seconds", allDone.await(maxTimeoutSeconds, TimeUnit.SECONDS));
        } finally {
            threadPool.shutdownNow();
        }
        assertTrue(message + "failed with exception(s)" + exceptions, exceptions.isEmpty());
    }
}

class MyRunnable implements Runnable {
    public void run() {
        try {
            Thread.sleep(10000);
        } catch (Exception e) {
        } finally {

        }
    }
}

引用:
Multithreaded code and concurrency

上一篇下一篇

猜你喜欢

热点阅读