I testes how fast the Atomic Integer in multithread with comparing synchronized method, but I got the result that Atomic Integer was slower than synchronized method.
I read Java API Reference and I understood Atomic Integer is faster than synchronized in multithread.
So I want to know the reason why I got the poor result with Atomic Integer. My test code was wrong?
Here is my code
import java.util.concurrent.atomic.AtomicInteger; public class AtomicThreadTest { // Number of thread to run private static final int THREAD_NUM = 1000; // Repetition number to count up private static final int ROOP_NUM = 200000; // Base counter class private abstract class Counter implements Runnable { @Override public void run() { for (int i = 0; i < ROOP_NUM; i++) { increment(); } } // Increment method public abstract void increment(); // Get result of calculation public abstract int getResult(); // Get name of the class @Override public String toString() { return getClass().getSimpleName(); } } // Use no thread safe private static int count = 0; private class NoThreadSafeCounter extends Counter { @Override public void increment() { count++; } @Override public int getResult() { return count; } } // Use volatile private static volatile int volatileCount = 0; private class VolatileCounter extends Counter { @Override public void increment() { volatileCount++; } @Override public int getResult() { return volatileCount; } } // Use synchronized private static int synchronizedCount = 0; private class SynchronizedCounter extends Counter { @Override public synchronized void increment() { synchronizedCount++; } @Override public int getResult() { return synchronizedCount; } } // Use AtomicInteger private static AtomicInteger atomicCount = new AtomicInteger(0); private class AtomicCounter extends Counter { @Override public void increment() { atomicCount.incrementAndGet(); } @Override public int getResult() { return atomicCount.get(); } } public static void main(String[] args) { AtomicThreadTest testClass = new AtomicThreadTest(); Counter[] testCounter = { testClass.new NoThreadSafeCounter(), testClass.new VolatileCounter(), testClass.new SynchronizedCounter(), testClass.new AtomicCounter(), }; for (Counter c : testCounter) { System.out.println("-------------------------"); System.out.printf("Test for class : %s\n", c.toString()); try { test(c); } catch (InterruptedException e) { System.out.println("Test halted"); } finally { System.out.println(""); System.gc(); } } System.out.println("-------------------------"); } public static void test(final Counter counter) throws InterruptedException { System.out.printf("Start with threads : %d, roop : %d\n", THREAD_NUM, ROOP_NUM); final long startTime = System.currentTimeMillis(); // Create THREAD_NUM threads and run them Thread[] threads = new Thread[THREAD_NUM]; for (int i = 0; i < THREAD_NUM; i++) { threads[i] = new Thread(counter); threads[i].start(); } // Wait for all threads other than this end while (Thread.activeCount() > 1) { Thread.sleep(10); } final long endTime = System.currentTimeMillis(); System.out.printf("Result %d, Expected %d\n", counter.getResult(), THREAD_NUM*ROOP_NUM); System.out.printf("Time to calc : %d\n", endTime-startTime); } } And I got the result below.
------------------------- Test for class : NoThreadSafeCounter Start with threads : 1000, roop : 200000 Result 198785583, Expected 200000000 Time to calc : 127 ------------------------- Test for class : VolatileCounter Start with threads : 1000, roop : 200000 Result 19162116, Expected 200000000 Time to calc : 4458 ------------------------- Test for class : SynchronizedCounter Start with threads : 1000, roop : 200000 Result 200000000, Expected 200000000 Time to calc : 8426 ------------------------- Test for class : AtomicCounter Start with threads : 1000, roop : 200000 Result 200000000, Expected 200000000 Time to calc : 15190
System.gc()as you don't know when it will get executed. You are not using a lot of memory, it is unlikely that you ever need to GC during the executionwhileloop at the end) is bad and consumes a lot of CPU. You should use something like a semaphore instead