You need to run the test for many iterations as ++
is quick and can run to completion before there is time for there to be a problem.
public static void main(String... args) throws InterruptedException {
for (int nThreads = 1; nThreads <= 16; nThreads*=2)
doThreadSafeTest(nThreads);
}
private static void doThreadSafeTest(final int nThreads) throws InterruptedException {
final int count = 1000 * 1000 * 1000;
ExecutorService es = Executors.newFixedThreadPool(nThreads);
final int[] num = {0};
for (int i = 0; i < nThreads; i++)
es.submit(new Runnable() {
public void run() {
for (int j = 0; j < count; j += nThreads)
num[0]++;
}
});
es.shutdown();
es.awaitTermination(10, TimeUnit.SECONDS);
System.out.printf("With %,d threads should total %,d but was %,d%n", nThreads, count, num[0]);
}
prints
With 1 threads should total 1,000,000,000 but was 1,000,000,000
With 2 threads should total 1,000,000,000 but was 501,493,584
With 4 threads should total 1,000,000,000 but was 319,482,716
With 8 threads should total 1,000,000,000 but was 261,092,117
With 16 threads should total 1,000,000,000 but was 202,145,371
with only 500K I got the following on a basic laptop. On a faster machine you can have a higher iteration count before a problem would be seen.
With 1 threads should total 500,000 but was 500,000
With 2 threads should total 500,000 but was 500,000
With 4 threads should total 500,000 but was 500,000
With 8 threads should total 500,000 but was 500,000
With 16 threads should total 500,000 but was 500,000