对多线程进行测试
在junit下, 很难对多线程的代码进行测试, 因此需要借助其他的方式, 比如Executor service框架. 最近要对一个监控类的输出情况写一个测试, 简单的跑一下输出格式是否跟预期一致.我这里借助了ThreadPoolExecutor+CompletionService. 即在结束前, 需要从线程池中拿到最后的执行结果. 我觉得多线程测试模式都应该是类似的, 备忘一下
public class MonitorHelperTest { private Worker[] workers; ExecutorService pool; CompletionService<Boolean> completionPool; List<Future<Boolean>> futures; static int count = 100; static int countPreThread = 1000; private static class Worker implements Callable<Boolean> { @Override public Boolean call() throws Exception { for (int i = 0; i < countPreThread; i++) { Action action = Action.values()[i % Action.values().length]; doFoo(i, action); } return true; } private void doFoo(int i, Action action) { long begin = MonitorHelper.addFetchAndGetNow(action, 1); try { foo(i); MonitorHelper.addTime(action, begin); MonitorHelper.addSuccess(action); } catch (Exception e) { MonitorHelper.addFailure(action); } } } @Before public void before() { pool = Executors.newFixedThreadPool(count, new ThreadFactory() { @Override public Thread newThread(Runnable r) { return new Thread(r, "worker"); } }); completionPool = new ExecutorCompletionService<Boolean>(pool); futures = new ArrayList<Future<Boolean>>(count); workers = new Worker[count]; for (int i = 0; i < count; i++) { workers[i] = new Worker(); } } @Test public void test() throws Exception { for (Worker worker : workers) { futures.add(completionPool.submit(worker)); } for (int i = 0; i < count; i++) { completionPool.take().get(); } } /** * @throws Exception * */ private static void foo(int i) throws Exception { if (i % 3 == 0) { TimeUnit.MILLISECONDS.sleep(50); throw new Exception(); } else { TimeUnit.MILLISECONDS.sleep(100); } }}