0% found this document useful (0 votes)
80 views4 pages

Java Concurrent Collections Guide

This document provides an introduction to Java's concurrent collection classes. It discusses how early Collections Framework classes were not thread-safe, but provided synchronized wrappers. Java 5 introduced truly concurrent collections that are thread-safe without external synchronization. These use techniques like copy-on-write, compare-and-swap, and locks to provide better performance than synchronized wrappers. Copy-on-write collections make immutable copies when written to avoid synchronization overhead, making them suitable for read-heavy use cases.

Uploaded by

jitendra99943
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
80 views4 pages

Java Concurrent Collections Guide

This document provides an introduction to Java's concurrent collection classes. It discusses how early Collections Framework classes were not thread-safe, but provided synchronized wrappers. Java 5 introduced truly concurrent collections that are thread-safe without external synchronization. These use techniques like copy-on-write, compare-and-swap, and locks to provide better performance than synchronized wrappers. Copy-on-write collections make immutable copies when written to avoid synchronization overhead, making them suitable for read-heavy use cases.

Uploaded by

jitendra99943
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 4

Concurrent Collections

This lesson gives a brief introduction about Java's concurrent collection classes.

Concurrent Collections

A bit of history before we delve into concurrent collection classes offered


by Java. When the Collections Framework was introduced in JDK 1.2, it
didn't come with collections that were synchronized. However, to cater
for multithreaded scenarios, the framework provided static methods to
wrap vanilla collections in thread-safe wrapper objects. These thread-
safe wrapper objects came to be known as wrapper collections.

Example Wrapper Collection

ArrayList<Integer> myList = new ArrayList<>();


List<Integer> syncList = Collections.synchronizedList(myList
);

For design pattern fans, this is an example of the decorator pattern.

Java 5 introduced thread-safe concurrent collections as part of a much


larger set of concurrency utilities. The concurrent collections remove the
necessity for client-side locking. In fact, external synchronization is not
even possible with these collections, as there is no one object which when
locked will synchronize all instance methods. If you need thread safety,
the concurrent collections generally provide much better
performance than synchronized (wrapper) collections. This is
primarily because their throughput is not reduced by the need to serialize
access, as is the case with synchronized collections. Synchronized
collections also suffer from the overhead of managing locks, which can be
high if there is much contention.

The concurrent collections use a variety of ways to achieve thread-safety


while avoiding traditional synchronization for better performance. These
are:

Copy on Write: Concurrent collections utilizing this scheme are


suitable for read-heavy use cases. An immutable copy is created of
the backing collection and whenever a write operation is attempted,
the copy is discarded and a new copy with the change is created.
Reads of the collection don’t require any synchronization, though
synchronization is needed briefly when the new array is being
created. Examples include CopyOnWriteArrayList and
CopyOnWriteArraySet

Compare and Swap: Consider a computation in which the value of a


single variable is used as input to a long-running calculation whose
eventual result is used to update the variable. Traditional
synchronization makes the whole computation atomic, excluding any
other thread from concurrently accessing the variable. This reduces
opportunities for parallel execution and hurts throughput. An
algorithm based on CAS behaves differently: it makes a local copy of
the variable and performs the calculation without getting exclusive
access. Only when it is ready to update the variable does it call CAS,
which in one atomic operation compares the variable’s value with its
value at the start and, if they are the same, updates it with the new
value. If they are not the same, the variable must have been modified
by another thread; in this situation, the CAS thread can try the whole
computation again using the new value, or give up, or— in some
algorithms — continue, because the interference will have actually
done its work for it! Collections using CAS include
ConcurrentLinkedQueue and ConcurrentSkipListMap .

Lock: Some collection classes use Lock to divide up the collection


into multiple parts that can be locked separately resulting in
improved concurrency. For example, LinkedBlockingQueue has
separate locks for the head and tail ends of the queue, so that
elements can be added and removed in parallel. Other collections
using these locks include ConcurrentHashMap and most of the
implementations of BlockingQueue .

CopyOnWrite Example
Lets take an example with a regular ArrayList along with a
CopyOnWriteArrayList . We will measure the time it takes to add an item to
an already initialized array. The output from running the code widget
below demonstrates that the CopyOnWriteArrayList takes much more time
than a regular ArrayList because under the hood, all the elements of the
CopyOnWriteArrayList object get copied thus making an insert operation
that much more expensive.

import java.util.concurrent.CopyOnWriteArrayList;
import java.util.*;

/**
* Java program to illustrate CopyOnWriteArrayList
*/
public class main
{
public static void main(String[] args)
throws InterruptedException
{
//Initializing a regular Arraylist
ArrayList<Integer> array_list = new ArrayList<>();
array_list.ensureCapacity(500000);
//Initializing a new CopyOnWrite Arraylist with 500,000 numbers
CopyOnWriteArrayList<Integer> numbers = new CopyOnWriteArrayList<>(array_list);

//Calculating the time it takes to add a number in CopyOnWrite Arraylist


long startTime = System.nanoTime();
numbers.add(500001);
long endTime = System.nanoTime();
long duration = (endTime - startTime);

//Calculating the time it takes to add a number in regular Arraylist


long startTime_al = System.nanoTime();
array_list.add(500001);
long endTime_al = System.nanoTime();
long duration_al = (endTime_al - startTime_al);

System.out.println("Time taken by a regular arraylist: "+ duration_al + " nano seconds");


System.out.println("Time taken by a CopyOnWrite arraylist: "+ duration + " nano seconds")

}
}

You might also like