# Synchronized vs Concurrent Collection

In 
Published 2022-12-03

# Explanation

This tutorial explains what is the difference between a Synchronized Collection and a Concurrent Collection.

The collections like PriorityQueue, ArrayList, LinkedList, HashSet, LinkedHashSet, TreeSet are not thread-safe. We can receive errors like ConcurrentModificationException when dealing with multiple threads.

For instance, as ArrayList is non-synchronized, multiple thread can access the ArrayList at same time so Thread1 and Thread2 can perform their tasks on ArrayList at same time which will produce inconsistent results and unexpected errors.

In a multi-threading environment, we need to take care of concurrency. For this, we can use the old Vector (similar to ArrayList, but synchronized), we can create synchronized collections or concurrent collections.

Here we have a comparison between the Synchronized Collections and the Concurrent Collections:

Feature Synchronized Collections Concurrent Collections
Thread Safe YES YES
Improved synchronization NO YES

The most used concurrent collection classes are : ConcurrentHashMap, CopyOnWriteArrayList and CopyOnWriteSet.

# Synchronized collections - example

Here we have an example of using synchronized collections:

package com.exampe.java;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.List;

@SpringBootApplication
public class DemoApplication {

	public static void main(String[] args) throws InterruptedException {

		SpringApplication.run(DemoApplication.class, args);

		System.out.println("--------------------------------------------");

		List<String> carList = new ArrayList<String>();

		carList.add("Audi");
		carList.add("Renault");
		carList.add("Peugeot");
		carList.add("Dacia");

		// Synchronizing ArrayList in Java
		Collection<String> carListSync = Collections.synchronizedList(carList);

		for (String c : carListSync) {
			System.out.println("car= " + c);
		}
		
		System.out.println("--------------------------------------------");
		System.out.println("End of the execution");
	}
}

In the same manner we can create synchronized maps and sets:

Set<String> set = new HashSet<String>();
Set<String> synSet = Collections.synchronizedSet(set);
Map<Integer, String> syncMap = Collections.synchronizedMap(new HashMap<>());

Here we have an example of using concurrent collections:

DemoApplication.java
package com.exampe.java;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

import java.util.concurrent.CopyOnWriteArrayList;

@SpringBootApplication
public class DemoApplication {

	public static void main(String[] args) throws InterruptedException {

		SpringApplication.run(DemoApplication.class, args);

		System.out.println("--------------------------------------------");

		CopyOnWriteArrayList<String> carList = new CopyOnWriteArrayList<>();

		// safe to use with multiple threads
		carList.add("Audi");
		carList.add("Renault");
		carList.add("Peugeot");
		carList.add("Dacia");

		for (String c : carList) {
			System.out.println("car= " + c);
		}

		System.out.println("--------------------------------------------");
		System.out.println("End of the execution");
	}
}

In the same manner we can use ConcurrentHashMap, and CopyOnWriteSet.

# Concurrent collections - example

In the following example we can see how we can use CopyOnWriteArrayList (in real life the things are more complex, because the usage of the threads):

Demo1Application.java
package com.example.demo;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

import java.util.ArrayList;
import java.util.Iterator;
import java.util.concurrent.CopyOnWriteArrayList;

@SpringBootApplication
public class Demo1Application {

    public static void main(String[] args) {
        SpringApplication.run(Demo1Application.class, args);

        // create a CopyOnWriteArrayList using an array
        String array1[] = {"Audi", "Peugeot", "Ford"};
        CopyOnWriteArrayList<String> list1 = new CopyOnWriteArrayList<>(array1);

        // create a CopyOnWriteArrayList without initial values
        ArrayList<String> aList = new ArrayList<>();
        aList.add("BMW");
        aList.add("Nissan");
        CopyOnWriteArrayList<String> list2 = new CopyOnWriteArrayList<>(aList);

        // iterate through the CopyOnWriteArrayList
        list1.stream().forEach(System.out::println);

        System.out.println("-------------");

        // iterate through the CopyOnWriteArrayList using an Iterator
        Iterator itr = list2.iterator();
        while (itr.hasNext())
            System.out.println(itr.next());
	}
}

When we run this example we can see:

Audi
Peugeot
Ford
-------------
BMW
Nissan