ExecutionQueue { public void submit(Runnable runnable) { synchronized (queueLock) { queue.add(runnable); maybePollAndExecute(); } } ExecutionQueue(Executor executor);  ExecutionQueue(Executor executor, int concurrencyLimit); void submit(Runnable runnable); void submitToHead(Runnable runnable); void pause(); void resume();  }
@Test public void testSubmitIsLinearWhenConcurrencyIs1() { ExecutionQueue queue = new ExecutionQueue(executor, 1); AtomicBoolean failed = new AtomicBoolean(false); AtomicInteger n = new AtomicInteger(0); for (int i = 0; i < 1000000; i++) { final int ii = i; queue.submit(() -> { int nn = n.getAndIncrement(); if (ii != nn) { System.out.println("n=" + nn + " i=" + ii); failed.set(true); } }); } assertFalse(failed.get()); }
@Test public void testWithConcurrency() throws InterruptedException { ExecutionQueue queue = new ExecutionQueue(executor, 4); final CountDownLatch latch = new CountDownLatch(100000); final AtomicInteger count = new AtomicInteger(); for (int i = 0; i < 100000; i++) { queue.submit(() -> { count.incrementAndGet(); latch.countDown(); }); } latch.await(); assertEquals(count.get(), 100000); }