Close

Java - AtomicBoolean, AtomicInteger and AtomicLong Examples

[Updated: May 24, 2018, Created: May 21, 2018]

In this tutorial we will see basic use of AtomicBoolean, AtomicInteger and AtomicLong. Each of this classes provide access and updates to a single variable of the corresponding type.

AtomicBoolean Example

This class wraps boolean value to be updated atomically. In this example we want to lazily initialize some code only once. The initializing method is accessed by multiple threads.

Without AtomicBoolean

package com.logicbig.example;

import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;

public class NonAtomicBooleanExample {
  private static boolean init;

  public static void init() {
      if (!init) {
          System.out.println("initializing");
          //initialize some expensive stuff
          init = true;
      }
  }

  public static void main(String[] args) throws InterruptedException {
      int c = 10;
      ExecutorService es = Executors.newFixedThreadPool(c);
      for (int i = 0; i < c; i++) {
          es.execute(NonAtomicBooleanExample::init);
      }
      es.shutdown();
      es.awaitTermination(10, TimeUnit.MINUTES);
  }
}
initializing
initializing
initializing
initializing
initializing

The problem with above code is, the two actions i.e. reading boolean variable 'init' and changing it's value to true, are not atomic.

With AtomicBoolean

Let's fix above code by replacing boolean with AtomicBoolean

package com.logicbig.example;

import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicBoolean;

public class AtomicBooleanExample {
  private static AtomicBoolean init = new AtomicBoolean();

  public static void init() {
      if (init.compareAndSet(false, true)) {
          System.out.println("initializing");
          //initialize some expensive stuff
      }
  }

  public static void main(String[] args) throws InterruptedException {
      int c = 10;
      ExecutorService es = Executors.newFixedThreadPool(c);
      for (int i = 0; i < c; i++) {
          es.execute(AtomicBooleanExample::init);
      }
      es.shutdown();
      es.awaitTermination(10, TimeUnit.MINUTES);
  }
}
initializing

AtomicInteger Example

without AtomicInteger

package com.logicbig.example;

import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;

public class NonAtomicIntegerExample {
  private static int num;

  public static void main(String[] args) throws InterruptedException {
      for (int k = 0; k < 10; k++) {
          num = 0;
          ExecutorService es = Executors.newFixedThreadPool(2);
          es.execute(() -> {
              for (int i = 0; i < 10000; i++) {
                  num++;
              }
          });
          es.execute(() -> {
              for (int i = 0; i < 10000; i++) {
                  num++;
              }
          });
          es.shutdown();
          es.awaitTermination(10, TimeUnit.MINUTES);
          System.out.println(num);
      }
  }
}
20000
13821
13425
12734
11173
12842
11961
20000
20000
18467

In above example the total sum is not always 2000, that's because the increment operation num++ is not atomic (as we saw here).

With AtomicInteger

package com.logicbig.example;

import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicInteger;

public class AtomicIntegerExample {
  private static AtomicInteger num = new AtomicInteger();

  public static void main(String[] args) throws InterruptedException {
      for (int k = 0; k < 10; k++) {
          num.set(0);
          ExecutorService es = Executors.newFixedThreadPool(2);
          es.execute(() -> {
              for (int i = 0; i < 10000; i++) {
                  num.incrementAndGet();
              }
          });
          es.execute(() -> {
              for (int i = 0; i < 10000; i++) {
                  num.incrementAndGet();
              }
          });

          es.shutdown();
          es.awaitTermination(10, TimeUnit.MINUTES);
          System.out.println(num.get());
      }
  }
}
20000
20000
20000
20000
20000
20000
20000
20000
20000
20000

AtomicLong

It is very similar to AtomicInteger and wraps a long variable atomically.

Without AtomicLong

package com.logicbig.example;

import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;

public class NonAtomicLongExample {
  private static long sum;

  public static void main(String[] args) throws InterruptedException {
      for (int k = 0; k < 5; k++) {
          sum = 0;
          ExecutorService es = Executors.newFixedThreadPool(50);
          for (int i = 1; i <= 50; i++) {
              int finalI = i;
              es.execute(() -> {
                  sum += Math.pow(2, finalI);
              });
          }
          es.shutdown();
          es.awaitTermination(10, TimeUnit.MINUTES);
          System.out.println(sum);
      }
  }
}
2251799813685244
2251799813685246
2251799813685246
2251799813685182
2251799813685246

The sum of 2^1+2^2+2^3.....2^50 should always be 2251799813685246.

With AtomicLong

package com.logicbig.example;

import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicLong;

public class AtomicLongExample {
  private static AtomicLong sum = new AtomicLong();

  public static void main(String[] args) throws InterruptedException {
      for (int k = 0; k < 5; k++) {
          sum.set(0);
          ExecutorService es = Executors.newFixedThreadPool(50);
          for (int i = 1; i <= 50; i++) {
              int finalI = i;
              es.execute(() -> {
                  sum.addAndGet((long) Math.pow(2, finalI));
              });
          }
          es.shutdown();
          es.awaitTermination(10, TimeUnit.MINUTES);
          System.out.println(sum);
      }
  }
}
2251799813685246
2251799813685246
2251799813685246
2251799813685246
2251799813685246

Example Project

Dependencies and Technologies Used:

  • JDK 10
  • Maven 3.3.9

AtomicBoolean, AtomicInteger and AtomicLong Examples Select All Download
  • atomic-variables-example
    • src
      • main
        • java
          • com
            • logicbig
              • example
                • AtomicBooleanExample.java

    See Also