package org.simpleframework.transport.trace; import java.text.DecimalFormat; import java.util.Queue; import java.util.concurrent.BlockingQueue; import java.util.concurrent.ConcurrentLinkedQueue; import java.util.concurrent.CountDownLatch; import java.util.concurrent.Executor; import java.util.concurrent.LinkedBlockingQueue; import java.util.concurrent.atomic.AtomicBoolean; import java.util.concurrent.atomic.AtomicLong; import java.util.concurrent.locks.LockSupport; import junit.framework.TestCase; import org.simpleframework.common.thread.ConcurrentExecutor; public class CompareQueueTest extends TestCase { private static final int TEST_DURATION = 10000; private static final int THREAD_COUNT = 100; private final Executor blockingReadExecutor = new ConcurrentExecutor(BlockingConsumer.class, THREAD_COUNT); private final Executor concurrentReadExecutor = new ConcurrentExecutor(ConcurrentConsumer.class, THREAD_COUNT); private final Executor writeExecutor = new ConcurrentExecutor(Producer.class, THREAD_COUNT); public void testLinkedBlockingQueue() throws Exception { BlockingQueue<Object> queue = new LinkedBlockingQueue<Object>(); AtomicBoolean active = new AtomicBoolean(true); AtomicLong writeCount = new AtomicLong(); AtomicLong readCount = new AtomicLong(); CountDownLatch startLatch = new CountDownLatch(THREAD_COUNT); CountDownLatch stopLatch = new CountDownLatch(THREAD_COUNT); DecimalFormat format = new DecimalFormat("###,###,###"); for(int i = 0; i < THREAD_COUNT; i++) { BlockingConsumer consumer = new BlockingConsumer(queue, stopLatch, active, readCount); blockingReadExecutor.execute(consumer); } Thread.sleep(1000); for(int i = 0; i < THREAD_COUNT; i++) { Producer producer = new Producer(queue, startLatch, active, writeCount); writeExecutor.execute(producer); } Thread.sleep(TEST_DURATION); active.set(false); stopLatch.await(); System.err.printf("read=%s write=%s%n", format.format(readCount.get()), format.format(writeCount.get())); } public void testConcurrentQueue() throws Exception { Queue<Object> queue = new ConcurrentLinkedQueue<Object>(); AtomicBoolean active = new AtomicBoolean(true); AtomicLong writeCount = new AtomicLong(); AtomicLong readCount = new AtomicLong(); CountDownLatch startLatch = new CountDownLatch(THREAD_COUNT); CountDownLatch stopLatch = new CountDownLatch(THREAD_COUNT); DecimalFormat format = new DecimalFormat("###,###,###"); for(int i = 0; i < THREAD_COUNT; i++) { ConcurrentConsumer consumer = new ConcurrentConsumer(queue, stopLatch, active, readCount); concurrentReadExecutor.execute(consumer); } Thread.sleep(1000); for(int i = 0; i < THREAD_COUNT; i++) { Producer producer = new Producer(queue, startLatch, active, writeCount); writeExecutor.execute(producer); } Thread.sleep(TEST_DURATION); active.set(false); stopLatch.await(); System.err.printf("read=%s write=%s%n", format.format(readCount.get()), format.format(writeCount.get())); } private static class Producer implements Runnable { private final Queue<Object> queue; private final AtomicBoolean active; private final AtomicLong count; private final CountDownLatch latch; public Producer(Queue<Object> queue, CountDownLatch latch, AtomicBoolean active, AtomicLong count) { this.queue = queue; this.active = active; this.count = count; this.latch = latch; } public void run() { try { latch.countDown(); latch.await(); while(active.get()) { Long value = count.getAndIncrement(); queue.offer(value); } } catch(Exception e) { e.printStackTrace(); } } } private static class ConcurrentConsumer implements Runnable { private final Queue<Object> queue; private final AtomicBoolean active; private final AtomicLong count; private final CountDownLatch latch; public ConcurrentConsumer(Queue<Object> queue, CountDownLatch latch, AtomicBoolean active, AtomicLong count) { this.queue = queue; this.active = active; this.count = count; this.latch = latch; } public void run() { try { while(active.get()) { Object value = queue.poll(); if(value != null) { count.getAndIncrement(); } else { LockSupport.parkNanos(100); } } latch.countDown(); latch.await(); }catch(Exception e) { e.printStackTrace(); } } } private static class BlockingConsumer implements Runnable { private final BlockingQueue<Object> queue; private final AtomicBoolean active; private final AtomicLong count; private final CountDownLatch latch; public BlockingConsumer(BlockingQueue<Object> queue, CountDownLatch latch, AtomicBoolean active, AtomicLong count) { this.queue = queue; this.active = active; this.count = count; this.latch = latch; } public void run() { try { while(active.get()) { try { Object value = queue.take(); if(value != null) { count.getAndIncrement(); } }catch(Exception e) { e.printStackTrace(); } } latch.countDown(); latch.await(); }catch(Exception e) { e.printStackTrace(); } } } }