Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

AtomicInteger for limited sequence generation

Tags:

java

atomic

How can we use AtomicInteger for limited sequence generation say the sequence number has to be between 1 to 60. Once the sequence reaches 60 it has to start again from 1. I wrote this code though not quite sure wether this is thread safe or not?

public int getNextValue()
{
 int v;
 do
 {
   v = val.get();
   if ( v == 60)
   {
    val.set(1);
   }
 }
  while (!val.compareAndSet(v , v + 1));
   return v + 1;
  }
like image 563
satish Avatar asked Jun 02 '10 17:06

satish


People also ask

What is AtomicInteger and when to use?

An AtomicInteger is used in applications such as atomically incremented counters, and cannot be used as a replacement for an Integer . However, this class does extend Number to allow uniform access by tools and utilities that deal with numerically-based classes.

What is AtomicInteger and how it is useful in concurrent environment?

AtomicInteger class provides operations on underlying int value that can be read and written atomically, and also contains advanced atomic operations. AtomicInteger supports atomic operations on underlying int variable. It have get and set methods that work like reads and writes on volatile variables.

What is difference between Integer and AtomicInteger?

Integers are object representations of literals and are therefore immutable, you can basically only read them. AtomicIntegers are containers for those values. You can read and set them. Same as asigning a value to variable.

How do you declare AtomicInteger?

Creating an AtomicIntegerAtomicInteger atomicInteger = new AtomicInteger(); This example creates an AtomicInteger with the initial value 0 . If you want to create an AtomicInteger with an initial value, you can do so like this: AtomicInteger atomicInteger = new AtomicInteger(123);


3 Answers

You could do

return val.getAndIncrement() % 60;

Unless you're concerned with exceeding the integer max-value (2147483647). If that is a concern, you could have a look at the getAndIncrement implementation:

public final int getAndIncrement() {
    for (;;) {
        int current = get();
        int next = current + 1;
        if (compareAndSet(current, next))
            return current;
    }
}

All you need to change is the int next... line to something like:

int next = (current + 1) % 60;

Oops. This loops through 0->59. You needed 1->60, so add one to the return-value to get the desired result.

like image 50
aioobe Avatar answered Oct 31 '22 00:10

aioobe


You can do this in a single line using Java 8.

AtomicInteger counter = new AtomicInteger();

public int getNextValue() {
    return counter.updateAndGet(n -> (n >= 60) ? 1 : n + 1);
}
like image 34
Kenny Colliander Nordin Avatar answered Oct 30 '22 22:10

Kenny Colliander Nordin


If you make the method synchronized then it will be threadsafe as long as the val is nowhere else accessed. The approach is however a bit cumbersome, I'd rewrite it as follows:

public synchronized int getNextValue() {
    val.compareAndSet(60, 0); // Set to 0 if current value is 60.
    return val.incrementAndGet();
}

This gives 1 until with 60 back inclusive. If you actually need 1 until with 59, then replace 60 by 59.

like image 24
BalusC Avatar answered Oct 31 '22 00:10

BalusC