My experiments with technology

java.util.concurrent.atomic: How to use Java Atomic Classes? AtomicInteger

August 28, 2009 · Leave a Comment

It has been some time since the release of Java 5. It introduced a number of improvements in terms of classes to handle concurrency concerns. Today I will cruising thru the java.util.concurrent.atomic package and looking at the package’s relevance in tackling real-life issues.

Let’s get started with the most basic requirements. Assume that you have a web site that maintains the number of users accessing a page. The counter information is not persisted beyond the web site up time. Therefore, we just need a counter to maintain a count of the number of users accessing a page. This can be achieved by creating a counter which is incremented on every page access. To ensure precise measurement, the counter needs to be incremented by a single thread and no other thread should access the counter variable. In pre Java 5 days, we would have to control access to the counter variable using a synchronized block. Here’s the sample code to do it:

Let’s get started with the most basic requirements. Assume that you have a web site that maintains the number of users accessing a page. The counter information is not persisted beyond the web site up time. Therefore, we just need a counter to maintain a count of the number of users accessing a page. This can be achieved by creating a counter which is incremented on every page access. To ensure precise measurement, the counter needs to be incremented by a single thread and no other thread should access the counter variable. In pre Java 5 days, we would have to control access to the counter variable using a synchronized block. Here’s the sample code to do it:

class Counter {

	private int count = 0;

	Counter () {

	}

	synchronized void increment() {
		count++;
	}

	int getCount() {
		return count;
	}
}

The synchronized is an all or nothing block. Java 5 provides an improved solution to handle the problem instead use the java.util.concurrent.atomic.AtomicInteger. This class implements the behavior as expected from Counter and in a more efficient manner. I have created the following test codes to verify the results:

public class CounterTest {

	public static void main(String[] args) {

		Counter counter = new Counter();

		for(int i=0; i< 1600; i++) {
			//This loop to get rid of any hotspot optimizations
			counter.increment();
		}

		long startTime = System.nanoTime();

		for(int i=0; i< 150000; i++) {
			counter.increment();
		}

		long endTime = System.nanoTime();
		double processingTime = (endTime - startTime)/Math.pow(10, 6);

		System.out.println("Processing Time (msec): " + processingTime + " Count: " + counter.getCount());

	}

}

public class AtomicIntegerTest {

	public static void main(String[] args) {
		AtomicInteger counter = new AtomicInteger(0);

		for(int i=0; i< 1600; i++) {
			//This loop to get rid of any hotspot optimizations
			counter.incrementAndGet();
		}

		long startTime = System.nanoTime();

		for(int i=0; i< 150000; i++) {
			counter.incrementAndGet();
		}

		long endTime = System.nanoTime();
		double processingTime = (endTime - startTime)/Math.pow(10, 6);

		System.out.println("Processing Time (msec): " + processingTime + " Count: " + counter.intValue());

	}

}
Running CounterTest displays the following:
Processing Time (msec): 18.196106 Count: 151600
Running AtomicIntegerTest displays the following:
Processing Time (msec): 11.212189 Count: 151600
There is a considerable improvement in performance. OK the next question is whether the counter is incrementing properly. Here’s how I tested it:
public class ConcurrencyTest {

	public static void main(String[] args) {
		AtomicInteger counter = new AtomicInteger(0);

		for(int i=0; i<100; i++) {
			Runnable runnable = new WorkerThread(counter);
			Thread t = new Thread(runnable);
			t.start();
		}

	}

}

class WorkerThread implements Runnable {

	AtomicInteger count = null;

	WorkerThread(AtomicInteger counter) {
		this.count = counter;
	}

	public void run() {
		int value = this.count.incrementAndGet();
		System.out.println(value);
	}
}
The output of the ConcurrencyTest run is a sequential value starting from 1 and ending at 100.

There are AtomicIntegerArray and AtomicLongArray classes.Apparently there is no AtomicFloat or AtomicDouble. The reason is explained in a foot note in the package summary.

You can also hold floats using Float.floatToIntBits and Float.intBitstoFloat conversions, and doubles using Double.doubleToLongBits and Double.longBitsToDouble conversions.

Categories: atomic · concurrency
Tagged: ,

0 responses so far ↓

  • There are no comments yet...Kick things off by filling out the form below.

Leave a Comment