下面方法摘录自 http://www.planetgeek.ch/2009/08/25/how-to-find-a-concurrency-bug-with-java/, 用来测试多线程并发执行的方法。
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());
}
此方法接受三个参数:分别为错误消息, 并发执行的Runner列表,以及并发执行的超时时间。
方法中会启用一个线程池, 并将参数中的所有的Runner都准备好后并发执行runner方法, 并将所有的执行异常存放在一个list中, 如果方法在规定时间内执行完, 并且异常列表为空的情况认为方法正确执行。
原创文章,作者:ItWorker,如若转载,请注明出处:https://blog.ytso.com/tech/pnotes/10470.html