From ac27ebd995e43489f2e9680b305bccafb8de0529 Mon Sep 17 00:00:00 2001 From: Mike Jensen Date: Fri, 3 Jan 2014 16:24:11 -0700 Subject: [PATCH] Reduced code duplication by combining these three very similar tests into a single file. --- test/AtomicIntegerTest.java | 96 -------------- test/AtomicLongTest.java | 96 -------------- test/AtomicReferenceTest.java | 80 ------------ test/AtomicTests.java | 231 ++++++++++++++++++++++++++++++++++ 4 files changed, 231 insertions(+), 272 deletions(-) delete mode 100644 test/AtomicIntegerTest.java delete mode 100644 test/AtomicLongTest.java delete mode 100644 test/AtomicReferenceTest.java create mode 100644 test/AtomicTests.java diff --git a/test/AtomicIntegerTest.java b/test/AtomicIntegerTest.java deleted file mode 100644 index 7e2326b31f..0000000000 --- a/test/AtomicIntegerTest.java +++ /dev/null @@ -1,96 +0,0 @@ -import java.util.concurrent.atomic.AtomicBoolean; -import java.util.concurrent.atomic.AtomicInteger; - -public class AtomicIntegerTest { - private static void runTest(final boolean increment, - final int threadCount, - final int iterationsPerThread) { - final AtomicInteger result = new AtomicInteger(); - final AtomicInteger threadDoneCount = new AtomicInteger(); - // only using an AtomicBoolean here so I don't need two variables to do the synchronize/wait/notify - final AtomicBoolean threadsStart = new AtomicBoolean(false); - - for (int i = 0; i < threadCount; i++) { - new Thread(new Runnable() { - @Override - public void run() { - try { - try { - waitTillReady(); - } catch (InterruptedException e) { - // let thread exit - return; - } - doOperation(); - } finally { - synchronized (threadDoneCount) { - threadDoneCount.incrementAndGet(); - - threadDoneCount.notifyAll(); - } - } - } - - private void waitTillReady() throws InterruptedException { - synchronized (threadsStart) { - while (! threadsStart.get()) { - threadsStart.wait(); - } - } - } - - private void doOperation() { - boolean flip = true; - for (int i = 0; i < iterationsPerThread; i++) { - if (flip) { - if (increment) { - result.incrementAndGet(); - } else { - result.decrementAndGet(); - } - flip = false; - } else { - if (increment) { - result.getAndIncrement(); - } else { - result.getAndDecrement(); - } - flip = true; - } - } - } - }).start(); - } - - synchronized (threadsStart) { - threadsStart.set(true); - - threadsStart.notifyAll(); - } - - synchronized (threadDoneCount) { - while (threadDoneCount.get() < threadCount) { - try { - threadDoneCount.wait(); - } catch (InterruptedException e) { - // let thread exit - return; - } - } - } - - int expectedResult = threadCount * iterationsPerThread; - if (! increment) { - expectedResult *= -1; - } - int resultValue = result.get(); - if (resultValue != expectedResult) { - throw new IllegalStateException(resultValue + " != " + expectedResult); - } - } - - public static void main(String[] args) { - runTest(true, 10, 100); - runTest(false, 10, 100); - } -} diff --git a/test/AtomicLongTest.java b/test/AtomicLongTest.java deleted file mode 100644 index 1ec9c89303..0000000000 --- a/test/AtomicLongTest.java +++ /dev/null @@ -1,96 +0,0 @@ -import java.util.concurrent.atomic.AtomicBoolean; -import java.util.concurrent.atomic.AtomicLong; - -public class AtomicLongTest { - private static void runTest(final boolean increment, - final int threadCount, - final int iterationsPerThread) { - final AtomicLong result = new AtomicLong(); - final AtomicLong threadDoneCount = new AtomicLong(); - // only using an AtomicBoolean here so I don't need two variables to do the synchronize/wait/notify - final AtomicBoolean threadsStart = new AtomicBoolean(false); - - for (int i = 0; i < threadCount; i++) { - new Thread(new Runnable() { - @Override - public void run() { - try { - try { - waitTillReady(); - } catch (InterruptedException e) { - // let thread exit - return; - } - doOperation(); - } finally { - synchronized (threadDoneCount) { - threadDoneCount.incrementAndGet(); - - threadDoneCount.notifyAll(); - } - } - } - - private void waitTillReady() throws InterruptedException { - synchronized (threadsStart) { - while (! threadsStart.get()) { - threadsStart.wait(); - } - } - } - - private void doOperation() { - boolean flip = true; - for (int i = 0; i < iterationsPerThread; i++) { - if (flip) { - if (increment) { - result.incrementAndGet(); - } else { - result.decrementAndGet(); - } - flip = false; - } else { - if (increment) { - result.getAndIncrement(); - } else { - result.getAndDecrement(); - } - flip = true; - } - } - } - }).start(); - } - - synchronized (threadsStart) { - threadsStart.set(true); - - threadsStart.notifyAll(); - } - - synchronized (threadDoneCount) { - while (threadDoneCount.get() < threadCount) { - try { - threadDoneCount.wait(); - } catch (InterruptedException e) { - // let thread exit - return; - } - } - } - - long expectedResult = threadCount * iterationsPerThread; - if (! increment) { - expectedResult *= -1; - } - long resultValue = result.get(); - if (resultValue != expectedResult) { - throw new IllegalStateException(resultValue + " != " + expectedResult); - } - } - - public static void main(String[] args) { - runTest(true, 10, 100); - runTest(false, 10, 100); - } -} diff --git a/test/AtomicReferenceTest.java b/test/AtomicReferenceTest.java deleted file mode 100644 index 2ebce10475..0000000000 --- a/test/AtomicReferenceTest.java +++ /dev/null @@ -1,80 +0,0 @@ -import java.util.concurrent.atomic.AtomicBoolean; -import java.util.concurrent.atomic.AtomicInteger; -import java.util.concurrent.atomic.AtomicReference; - -public class AtomicReferenceTest { - private static void runTest(final int threadCount, - final int iterationsPerThread) { - final AtomicReference result = new AtomicReference(0); - final AtomicInteger threadDoneCount = new AtomicInteger(0); - // only using an AtomicBoolean here so I don't need two variables to do the synchronize/wait/notify - final AtomicBoolean threadsStart = new AtomicBoolean(false); - - for (int i = 0; i < threadCount; i++) { - new Thread(new Runnable() { - @Override - public void run() { - try { - try { - waitTillReady(); - } catch (InterruptedException e) { - // let thread exit - return; - } - doOperation(); - } finally { - synchronized (threadDoneCount) { - threadDoneCount.incrementAndGet(); - - threadDoneCount.notifyAll(); - } - } - } - - private void waitTillReady() throws InterruptedException { - synchronized (threadsStart) { - while (! threadsStart.get()) { - threadsStart.wait(); - } - } - } - - private void doOperation() { - for (int i = 0; i < iterationsPerThread; i++) { - Integer current = result.get(); - while (! result.compareAndSet(current, current + 1)) { - current = result.get(); - } - } - } - }).start(); - } - - synchronized (threadsStart) { - threadsStart.set(true); - - threadsStart.notifyAll(); - } - - synchronized (threadDoneCount) { - while (threadDoneCount.get() < threadCount) { - try { - threadDoneCount.wait(); - } catch (InterruptedException e) { - // let thread exit - return; - } - } - } - - long expectedResult = threadCount * iterationsPerThread; - Integer resultValue = result.get(); - if (resultValue != expectedResult) { - throw new IllegalStateException(resultValue + " != " + expectedResult); - } - } - - public static void main(String[] args) { - runTest(10, 100); - } -} diff --git a/test/AtomicTests.java b/test/AtomicTests.java new file mode 100644 index 0000000000..9dab42703e --- /dev/null +++ b/test/AtomicTests.java @@ -0,0 +1,231 @@ +import java.util.concurrent.atomic.AtomicBoolean; +import java.util.concurrent.atomic.AtomicInteger; +import java.util.concurrent.atomic.AtomicLong; +import java.util.concurrent.atomic.AtomicReference; + + +public class AtomicTests { + private static final int threadCount = 10; + private static final int iterationsPerThread = 100; + + public static void main(String[] args) { + runAtomicIntegerTest(true); + runAtomicIntegerTest(false); + + runAtomicLongTest(true); + runAtomicLongTest(false); + + runAtomicReferenceTest(); + } + + private static void blockTillThreadsDone(AtomicInteger threadDoneCount) throws InterruptedException { + synchronized (threadDoneCount) { + while (threadDoneCount.get() < threadCount) { + threadDoneCount.wait(); + } + } + } + + private static void runAtomicIntegerTest(final boolean increment) { + final AtomicInteger result = new AtomicInteger(); + final AtomicInteger threadDoneCount = new AtomicInteger(); + // only using an AtomicBoolean here so I don't need two variables to do the synchronize/wait/notify + final AtomicBoolean threadsStart = new AtomicBoolean(false); + + Runnable operationRunnable = new Runnable() { + @Override + public void run() { + boolean flip = true; + for (int i = 0; i < iterationsPerThread; i++) { + if (flip) { + if (increment) { + result.incrementAndGet(); + } else { + result.decrementAndGet(); + } + flip = false; + } else { + if (increment) { + result.getAndIncrement(); + } else { + result.getAndDecrement(); + } + flip = true; + } + } + } + }; + + for (int i = 0; i < threadCount; i++) { + new Thread(new DelayedRunnable(threadsStart, + operationRunnable, + threadDoneCount)).start(); + } + + synchronized (threadsStart) { + threadsStart.set(true); + + threadsStart.notifyAll(); + } + + try { + blockTillThreadsDone(threadDoneCount); + } catch (InterruptedException e) { + // let thread exit + return; + } + + int expectedResult = threadCount * iterationsPerThread; + if (! increment) { + expectedResult *= -1; + } + int resultValue = result.get(); + if (resultValue != expectedResult) { + throw new IllegalStateException(resultValue + " != " + expectedResult); + } + } + + private static void runAtomicLongTest(final boolean increment) { + final AtomicLong result = new AtomicLong(); + final AtomicInteger threadDoneCount = new AtomicInteger(); + // only using an AtomicBoolean here so I don't need two variables to do the synchronize/wait/notify + final AtomicBoolean threadsStart = new AtomicBoolean(false); + + Runnable operationRunnable = new Runnable() { + @Override + public void run() { + boolean flip = true; + for (int i = 0; i < iterationsPerThread; i++) { + if (flip) { + if (increment) { + result.incrementAndGet(); + } else { + result.decrementAndGet(); + } + flip = false; + } else { + if (increment) { + result.getAndIncrement(); + } else { + result.getAndDecrement(); + } + flip = true; + } + } + } + }; + + for (int i = 0; i < threadCount; i++) { + new Thread(new DelayedRunnable(threadsStart, + operationRunnable, + threadDoneCount)).start(); + } + + synchronized (threadsStart) { + threadsStart.set(true); + + threadsStart.notifyAll(); + } + + try { + blockTillThreadsDone(threadDoneCount); + } catch (InterruptedException e) { + // let thread exit + return; + } + + long expectedResult = threadCount * iterationsPerThread; + if (! increment) { + expectedResult *= -1; + } + long resultValue = result.get(); + if (resultValue != expectedResult) { + throw new IllegalStateException(resultValue + " != " + expectedResult); + } + } + + private static void runAtomicReferenceTest() { + final AtomicReference result = new AtomicReference(0); + final AtomicInteger threadDoneCount = new AtomicInteger(0); + // only using an AtomicBoolean here so I don't need two variables to do the synchronize/wait/notify + final AtomicBoolean threadsStart = new AtomicBoolean(false); + + Runnable operationRunnable = new Runnable() { + @Override + public void run() { + for (int i = 0; i < iterationsPerThread; i++) { + Integer current = result.get(); + while (! result.compareAndSet(current, current + 1)) { + current = result.get(); + } + } + } + }; + + for (int i = 0; i < threadCount; i++) { + new Thread(new DelayedRunnable(threadsStart, + operationRunnable, + threadDoneCount)).start(); + } + + synchronized (threadsStart) { + threadsStart.set(true); + + threadsStart.notifyAll(); + } + + try { + blockTillThreadsDone(threadDoneCount); + } catch (InterruptedException e) { + // let thread exit + return; + } + + long expectedResult = threadCount * iterationsPerThread; + Integer resultValue = result.get(); + if (resultValue != expectedResult) { + throw new IllegalStateException(resultValue + " != " + expectedResult); + } + } + + private static class DelayedRunnable implements Runnable { + private final AtomicBoolean threadsStart; + private final Runnable operationRunnable; + private final AtomicInteger threadDoneCount; + + private DelayedRunnable(AtomicBoolean threadsStart, + Runnable operationRunnable, + AtomicInteger threadDoneCount) { + this.threadsStart = threadsStart; + this.operationRunnable = operationRunnable; + this.threadDoneCount = threadDoneCount; + } + + @Override + public void run() { + try { + try { + waitTillReady(); + } catch (InterruptedException e) { + // let thread exit + return; + } + operationRunnable.run(); + } finally { + synchronized (threadDoneCount) { + threadDoneCount.incrementAndGet(); + + threadDoneCount.notifyAll(); + } + } + } + + private void waitTillReady() throws InterruptedException { + synchronized (threadsStart) { + while (! threadsStart.get()) { + threadsStart.wait(); + } + } + } + } +}