What’s new with Concurrency in JDK 8: Class LongAdder

Lochana Ranaweera
Lochness Writes
Published in
2 min readDec 2, 2015

In today’s post I will discuss one Concurrency Utility Enhancement provided by Java 8.

Java 8 includes a class called LongAdder in java.util.concurrent.atomic package to yet again support atomic operations on a single variable concerning to long values. Let us first understand what is meant by an atomic operation. If an operation can be performed by multiple threads in parallel without using locks or synchronized blocks, such an operation is called an atomic operation For better performance,concurrent mutations of single variables should be carried out via atomic operations instead of locks.

I first wondered why JDK 8 has introduced this LongAdder class because an instance of class AtomicLong (JDK 5) can also deal with long values that are updated atomically. The reason, as many experts have pointed out, is when a large number of threads are updating a variable atomically using an operation like addition, high thread contention is anticipated. Here, thread contention is referred to the condition where one thread is waiting for a lock/object, in this case the variable reference, that is currently being held by another thread. A class like AtomicLong implements optimistic concurrency principles, where threads keep trying to carry out the update on the variable until the application allows to do so. As such, too many retries have a significant detrimental impact on performance of the program. Compared to AtomicLong, LongAdder offers much better performance according to this article, therefore using the class LongAdder instead of AtomicLong is recommended.

Let’s see an example on how to use the class LongAdder to add up all digits from 0 to 1000 using a number of threads.

LongAdder Example:

In the class LongAdderExample, I have created a new LongAdder instance called summingVariable. The Executors factory class results in an ExecutorService instance with a thread pool that re-uses a fixed number of threads (10 in this case). I have used the IntStream interface to generate a sequential ordered IntStream from 0 (inclusive) to 1001 (exclusive) by an incremental step of 1, so that I can have a sum of digits from 0–1000. Note that upper bound in the IntStream.range() method is excluded in the generated IntStream. A Callable task which can return a value unlike a Runnable task is defined to add the current digit to the summingVariable. The reason why I have called the invokeAll( ) method of the ExecutorService instance is to ensure all the tasks have been executed before the ExecutorService is shut down so that the threads do not keep running. Please refer to this tutorial if you need further detail on how ExecutorServices work.

--

--