@Test public void testMultithreadGenerator() {

    final int numSequenceBits = 12;
    final int numWorkerBits = 12;
    final IdGenerator worker = new IdGenerator(1, numWorkerBits, numSequenceBits);
    final int numThreads = 10;
    final int numRunnables = 20;
    final int numLoops = (int) (Math.pow(2, numSequenceBits) * 10);
    // Create hash set for all outputs
    final List<long[]> ids = new ArrayList<long[]>();
    for (int i = 0; i < numRunnables; i++) {
        ids.add(new long[numLoops]);
    }
    final CountDownLatch startLatch = new CountDownLatch(numThreads);
    final CountDownLatch doneLatch = new CountDownLatch(numRunnables);
    ExecutorService executor = Executors.newFixedThreadPool(numThreads);
    for (int i = 0; i < numRunnables; i++) {
        final long[] loopData = ids.get(i);
        Runnable r = new Runnable() {
            public void run() {
                startLatch.countDown();
                try {
                    startLatch.await();
                } catch (InterruptedException ie) {
                    throw new RuntimeException(ie);
                }
                for (int j = 0; j < numLoops; j++) {
                    loopData[j] = worker.getNextId();
                }
                doneLatch.countDown();
            }
        };
        executor.execute(r);
    }
    try {
        doneLatch.await();
    } catch (InterruptedException ie) {
        throw new RuntimeException(ie);
    }
    executor.shutdown();
    Set<Long> allids = new HashSet<Long>();
    // now compare the outputs. should not contain duplicates
    for (int i = 0; i < ids.size(); i++) {
        // compare to first element
        for (Long id : ids.get(i)) {
            assertFalse("index [" + i + "] not set earlier ("
                    + id.longValue() + ")", allids.contains(id.longValue()));
            allids.add(id.longValue());
        }
    }
}