JUnit4 测试多线程

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)

  • 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

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容

  • Spring Cloud为开发人员提供了快速构建分布式系统中一些常见模式的工具(例如配置管理,服务发现,断路器,智...
    卡卡罗2017阅读 135,323评论 19 139
  • 1. Java基础部分 基础部分的顺序:基本语法,类相关的语法,内部类的语法,继承相关的语法,异常的语法,线程的语...
    子非鱼_t_阅读 31,899评论 18 399
  • 对象的创建与销毁 Item 1: 使用static工厂方法,而不是构造函数创建对象:仅仅是创建对象的方法,并非Fa...
    孙小磊阅读 6,197评论 0 3
  • 文 / 戒闲 何静最近很烦,她一直随身携带的那块怀表不走了,跑了很多地方都没办法修好。 木木早就看出来了她的焦躁不...
    花一尧阅读 3,199评论 0 1
  • 刘世超 文魁大脑90天学习计划 第10天 1.5 今日学习:无 今日训练: 读数训练20分钟: 平均用时33s左右...
    24K超超老师阅读 2,844评论 0 0