マルチスレッドのテスト


junitではマルチスレッドのコードをテストすることは困難であるため、Executor serviceフレームワークのような他の方法が必要である.最近、モニタリングクラスの出力状況にテストを書き、出力フォーマットが予想通りに一致するかどうかを簡単に走ります.ここではThreadPoolExecutor+CompletionServicesを借りました.すなわち、終了前にスレッドプールから最後の実行結果を得る必要がある.マルチスレッドテストモードは似ていると思います.忘れないでください.
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);
        }
    }
}