January 15, 2024

AtomicInteger in Java With Examples

java.util.concurrent.atomic package in Java has classes that support lock free atomic operations. That means using classes contained in this package atomicity of operations is guaranteed for integer, long, boolean values along with object references and arrays with out using explicit synchronization or locks. In this post we'll discuss one of such class AtomicInteger in Java which provides an int value that may be updated atomically.

AtomicInteger in Java

AtomicInteger class which is part of java.util.concurrent.atomic package provides methods to get, set, increment, update, compare int value as an atomic operation that too with out using locks or synchronized keyword to regulate access to shared variable by multiple threads.

Atomic classes use CAS (Compare and Swap) to ensure data integrity using non-blocking algorithms. That’s why these classes are considered to be faster than locking where one thread acquires the object lock while other threads are blocked.

Java AtomicInteger Constructors

There are two constructors in AtomicInteger class.

  • AtomicInteger()- Creates a new AtomicInteger with 0 as initial value.
  • AtomicInteger(int initialValue)- Creates a new AtomicInteger initialized with the given initial value.

AtomicInteger Java examples

One of the common use is to provide an atomically incremented counter using an AtomicInteger. For that purpose incrementAndGet() method can be used which atomically increments the current value.

Atomically incremented counter using AtomicInteger
public class AtomicIntExample {
  public static void main(String[] args) {
    ExecutorService executor = Executors.newFixedThreadPool(2);
    AtomicInteger atomicInt = new AtomicInteger();
    for(int i = 0; i < 10; i++){
      executor.submit(()->System.out.println("Counter- " + atomicInt.incrementAndGet()));
    }
    executor.shutdown();
  }
}
Output
Counter- 1
Counter- 2
Counter- 3
Counter- 4
Counter- 5
Counter- 6
Counter- 7
Counter- 8
Counter- 9
Counter- 10

In the above example Runnable is implemented as a lambda expression. If you prefer Runnable implemented the old way here is the same example.

public class AtomicIntExample {
  public static void main(String[] args) {
    ExecutorService executor = Executors.newFixedThreadPool(2);
    AtomicInteger atomicInt = new AtomicInteger();
    CounterRunnable runnableTask = new  CounterRunnable(atomicInt);
    for(int i = 0; i < 10; i++){
      executor.submit(runnableTask);
    }
    executor.shutdown();
  }
}

class CounterRunnable implements Runnable{
  AtomicInteger atomicInt;
  CounterRunnable(AtomicInteger atomicInt){
    this.atomicInt = atomicInt;
  }
  @Override
  public void run() {
    System.out.println("Counter- " + atomicInt.incrementAndGet());		
  }
}

Methods in AtomicInteger class

Some of the atomic methods in the Java AtomicInteger class are as follows-

  • addAndGet(int delta)- Atomically adds the given value to the current value.
  • compareAndSet(int expect, int update)- Atomically sets the value to the given updated value if the current value == the expected value.
  • getAndDecrement()- Atomically decrements by one the current value.
  • getAndIncrement()- Atomically increments by one the current value.
  • getAndSet(int newValue)- Atomically sets to the given value and returns the old value.
  • getAndUpdate(IntUnaryOperator updateFunction)- Atomically updates the current value with the results of applying the given function, returning the previous value.
  • incrementAndGet()- Atomically increments by one the current value.

Comparing and setting value using AtomicInteger

You can compare and set value using compareAndSet() method which takes two arguments expected value and update. If expected value is equal to the current value of the AtomicInteger instance then the value is updated. Returns true if successful. False return indicates that the actual value was not equal to the expected value.

public class AtomicIntExample {
  public static void main(String[] args) {
    ExecutorService executor = Executors.newFixedThreadPool(2);
    AtomicInteger atomicInt = new AtomicInteger(0);
    
    for(int i = 1; i <= 10; i++){
      // delay between each update submission
      try {
        TimeUnit.MILLISECONDS.sleep(20);
      } catch (InterruptedException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
      }
      executor.submit(new RunnableTask(atomicInt, atomicInt.get(), i));
    }
    System.out.println("Updated value- " + atomicInt.get());
    executor.shutdown();
  }
}

class RunnableTask implements Runnable{
  AtomicInteger atomicInt;
  int expectedVal;
  int newVal;
  RunnableTask(AtomicInteger atomicInt, int expectedVal, int newVal){
    this.atomicInt = atomicInt;
    this.expectedVal = expectedVal;
    this.newVal = newVal;
  }
  @Override
  public void run() {
    System.out.println("Value updated- " + atomicInt.compareAndSet(expectedVal, newVal));		
  }
}
Output
Value updated- true
Value updated- true
Value updated- true
Value updated- true
Value updated- true
Value updated- true
Value updated- true
Value updated- true
Value updated- true
Value updated- true
Updated value- 10

That's all for the topic AtomicInteger in Java With Examples. If something is missing or you have something to share about the topic please write a comment.


You may also like

No comments:

Post a Comment