Small knowledge, big challenge! This article is participating in the creation activity of “Essential Tips for Programmers”.

1. Concurrent collections

The java.util.concurrent package was introduced in JDK1.5, where a set of thread-safe collections, called concurrent collections, is defined as an alternative to synchronous collections.

A non-thread-safe collection Concurrent collections A common interface
ArrayList CopyOnWriteArrayList List
LinkedList ConcurrentLinkedQueue Queue
HashSet CopyOnWriteArraySet Set
TreeSet ConcurrentSkipListSet SortedSet
HashMap ConcurrentHashMap Map
TreeMap ConcurrentSkipListMap SortedMap

Reference: www.bjpowernode.com/javathread/…

2. List is not safe

List collections are not thread-safe, and their use in a multithreaded environment may result in data inconsistencies or exceptions.

public class ListTest {
    public static void main(String[] args) {
        List<String> list = new ArrayList<>();

        for (int i = 1; i < 10; i++) {
            new Thread(() -> {
                list.add(UUID.randomUUID().toString().substring(0.5)); System.out.println(list); }, String.valueOf(i)).start(); }}}Copy the code

View the exception: concurrent abnormal ConcurrentModificationException

ArrayList is not secure in concurrent cases.

Resolve List insecurity

Method 1: Vector collection

public class ListTest {
    public static void main(String[] args) {
        List<String> list = new Vector<>();

        for (int i = 1; i < 10; i++) {
            new Thread(() -> {
                list.add(UUID.randomUUID().toString().substring(0.5)); System.out.println(list); }, String.valueOf(i)).start(); }}}Copy the code

The reason: Vector collections are thread-safe, and use the synchronized keyword in Vector collections to modify methods to be synchronized, allowing only one of the methods to be called by a single thread. Vector collections are also called synchronous collections.

Add ();

Method two: the Collections utility class

The Collections utility class provides a set of synchronizedXXX() methods to convert non-thread-safe Collections to thread-safe Collections, which are also synchronous Collections.

public class ListTest {
    public static void main(String[] args) {
        List<String> list = Collections.synchronizedList(new ArrayList<>());

        for (int i = 1; i < 10; i++) {
            new Thread(() -> {
                list.add(UUID.randomUUID().toString().substring(0.5)); System.out.println(list); }, String.valueOf(i)).start(); }}}Copy the code

Method 3: Concurrent collection CopyOnWriteArrayList, concurrent collection can be used as a substitute for synchronous collection.

public class ListTest {
    public static void main(String[] args) {
        List<String> list = new CopyOnWriteArrayList<>();

        for (int i = 1; i < 10; i++) {
            new Thread(() -> {
                list.add(UUID.randomUUID().toString().substring(0.5)); System.out.println(list); }, String.valueOf(i)).start(); }}}Copy the code

CopyOnWriteArrayList write operation source code analysis:

CopyOnWriteArrayList collection, which reads data without locking at all, and writes do not block reads. From the collection class name CopyOnWrite makes a copy of itself as it writes. That is, writing data to a collection does not modify the original content, but copies the original content of the collection to a copy, writes data to the copy, and then replaces the original data with the copy after writing.

Concurrent Collections CopyOnWriteArrayList than synchronous Vector set and the Collections. SynchronizedList () efficiency is high, because the two methods are used the synchronized, Locking synchronization is performed every time data is read, so they read data inefficiently.

3. Set is not safe

Like lists, sets are not safe in concurrent cases,

There are two ways to resolve Set insecurity:

1. SynchronizedSet () method of the Collections utility class

2. Concurrent set CopyOnWriteArraySet

4. Map is not secure

public class MapTest {
    public static void main(String[] args) {
        HashMap<Object, Object> map = new HashMap<>();
        for (int i = 1; i < 10; i++) {
            new Thread(() -> {
                map.put(Thread.currentThread().getName(),UUID.randomUUID().toString().substring(0.5)); System.out.println(map); }, String.valueOf(i)).start(); }}}Copy the code

Concurrent exceptions occur:

Resolve Map insecurity

1. Collections Synchronizes Collections

public class MapTest {
    public static void main(String[] args) {
        Map<String,String> map = Collections.synchronizedMap(new HashMap<>());

        for (int i = 1; i < 10; i++) {
            new Thread(() -> {
                map.put(Thread.currentThread().getName(),UUID.randomUUID().toString().substring(0.5)); System.out.println(map); }, String.valueOf(i)).start(); }}}Copy the code

Collections.synchronizedmap (new HashMap < > () returns a thread-safe Collections, used the decorator pattern, inside the thread-safe Collections, first to get the mutex lock, complicated with low efficiency.

2. ConcurrentHashMap collection

public class MapTest {
    public static void main(String[] args) {

        ConcurrentHashMap<Object, Object> map = new ConcurrentHashMap<>();
        for (int i = 1; i < 10; i++) {
            new Thread(() -> {
                map.put(Thread.currentThread().getName(),UUID.randomUUID().toString().substring(0.5)); System.out.println(map); }, String.valueOf(i)).start(); }}}Copy the code

ConcurrentHashMap is a set of highly concurrent thread-safe maps. Prior to JDK7, the ConcurrentHashMap collection used extremely fine-grained locks internally for thread-safety, or piecewise locking protocol, allowing concurrent operations of 16 threads by default. The ConcurrentHashMap collection has been improved in JDK8, using CAS operations to achieve thread safety.