📜  JavaConcurrentHashMap、HashTable和同步Map的区别

📅  最后修改于: 2021-09-14 02:33:23             🧑  作者: Mango

在这里,我们将一一讨论,然后在对这三者都有充分的了解后,再讨论差异。我们将首先讨论 ConcurrentHashMap,然后是 HashTable,最后是 Synchronized Map。让我们先从 ConcurrentHashMap 开始。

ConcurrentHashMap 的底层数据结构是HashTable。 ConcurrentHashMap 允许并发读取和线程安全更新操作。执行读操作的线程不需要任何锁,执行更新操作的线程需要锁,但它只是 Map 特定部分的锁(Bucket 级锁)。而不是通过内部将地图分成由并发级别定义的较小部分来实现整个地图的并发更新。默认并发级别为 16,即 ConcurrentHashMap 允许同时进行读取和 16 个写入(更新)操作。键和值都不允许使用 null 值。当一个线程在迭代时,另一个线程可以执行更新操作并且 ConcurrentHashMap 从不抛出 ConcurrentModificationException。

句法:

ConcurrentHashMap CHM = new  ConcurrentHashMap<>();

上面的构造函数创建了一个空的 ConcurrentHashMap

  • 默认初始容量等于 16
  • 默认填充率等于 0.75
  • 默认并发级别 16,其中 K 是键,V 是 ConcurrentHashMap 的值

例子:

Java
// Java program to illustrate ConcurrentHashMap
 
// Importing required packages
import java.io.*;
import java.util.*;
import java.util.concurrent.*;
 
// Main class
public class GFG {
 
    // Main driver method
    public static void main(String[] args)
    {
 
        // Creating ConcurrentHashMap class object
        // Declaring object of integer an string type
        ConcurrentHashMap chm
            = new ConcurrentHashMap<>();
 
        // Adding entry to ConcurrentHashMap
        // Custom input entries
        chm.put(65, "A");
        chm.put(66, "B");
 
        // Print and display the ConcurrentHashMap
        System.out.println(chm);
 
        // Adding the entry if the given entry is not
        // present in the ConcurrentHashMap Custom input
        // entries
        chm.putIfAbsent(67, "C");
        chm.putIfAbsent(68, "D");
 
        // Printand display the ConcurrentHashMap
        System.out.println(chm);
 
        // Removing entry With Key and Value as 68 and D
        chm.remove(68, "D");
 
        // Print and display the ConcurrentHashMap
        System.out.println(chm);
 
        // Replacing  Value of an entry
        chm.replace(66, "B", "E");
 
        // Again, print and display the ConcurrentHashMap
        System.out.println(chm);
    }
}


Java
// Java program to illustrate HashTable
 
// Importing required packages
import java.io.*;
import java.util.*;
 
// Main class
class GFG {
 
    // Main driver method
    public static void main(String[] args)
    {
 
        // Creating Hashtable object
        Hashtable ht = new Hashtable<>();
 
        // Adding entry to Hashtable
        // Custom input entries
        ht.put(65, "A");
        ht.put(66, "B");
        ht.put(67, "C");
        ht.put(68, "D");
 
        // Print and display the HashTable elements
        System.out.println(ht);
    }
}


Java
// Java program to demonstrate synchronizedMap() method
 
// Importing required pacakges
import java.io.*;
import java.util.*;
 
// Main class
public class GFG {
 
    // Main driver method
    public static void main(String[] args)
    {
 
        // Try block to check for exceptions
        try {
 
            // Creating object of HashMap
            // Declaring object of integer and string type
            HashMap map = new HashMap<>();
 
            // Adding entry to map object created above
            // Custom input entries
            map.put(65, "A");
            map.put(66, "B");
            map.put(67, "C");
            map.put(68, "D");
 
            // Print and display the map object
            System.out.println("Map is " + map);
 
            // Creating a synchronized map object
            // Declaring object of type integer and string
            Map synmap
                = Collections.synchronizedMap(map);
 
            // Print and display the synchronized map
            // elements
            System.out.println("Synchronized map is : "
                               + synmap);
        }
 
        // Catch block to handle the exceptions
        catch (IllegalArgumentException e) {
 
            // Display the exception on the console
            System.out.println(e);
        }
    }
}


输出
{65=A, 66=B}
{65=A, 66=B, 67=C, 68=D}
{65=A, 66=B, 67=C}
{65=A, 66=E, 67=C}

现在讨论第二个概念,即HashTable HashTable 的底层数据结构是HashTable。 HashTable 中的插入顺序是不保留的,它是基于键的哈希码。不允许重复键,但可以重复值。键和值都允许使用异构对象。键和值都不允许使用 null 值,否则我们会得到 RunTimeException,表示 NullPointerException。它实现了可序列化和可克隆的接口,但没有实现 RandomAccess。其中的每个方法都是同步的,因此 HashTable 对象是线程安全的。如果我们的频繁操作是搜索操作,HashTable 是最好的选择。

句法:

Hashtable ht = new Hashtable<>();

上面的构造函数创建了一个空的哈希表对象,初始默认容量为 11,默认填充率为 0.75。其中 K 是关键,V 是 哈希表的值。

例子:

Java

// Java program to illustrate HashTable
 
// Importing required packages
import java.io.*;
import java.util.*;
 
// Main class
class GFG {
 
    // Main driver method
    public static void main(String[] args)
    {
 
        // Creating Hashtable object
        Hashtable ht = new Hashtable<>();
 
        // Adding entry to Hashtable
        // Custom input entries
        ht.put(65, "A");
        ht.put(66, "B");
        ht.put(67, "C");
        ht.put(68, "D");
 
        // Print and display the HashTable elements
        System.out.println(ht);
    }
}
输出
{65=A, 68=D, 67=C, 66=B}

最后,在确定所有三个之间的决定性差异之前,先讨论同步地图。 synchronizedMap() 方法用于返回由指定映射支持的同步(线程安全)映射。这个方法存在于Java.util.Collections 中。

句法:

public static  Map synchronizedMap(Map M)

// where M is the map to be synchronized K is key 
//   and V is value for the resultant synchronized map.    

例子:

Java

// Java program to demonstrate synchronizedMap() method
 
// Importing required pacakges
import java.io.*;
import java.util.*;
 
// Main class
public class GFG {
 
    // Main driver method
    public static void main(String[] args)
    {
 
        // Try block to check for exceptions
        try {
 
            // Creating object of HashMap
            // Declaring object of integer and string type
            HashMap map = new HashMap<>();
 
            // Adding entry to map object created above
            // Custom input entries
            map.put(65, "A");
            map.put(66, "B");
            map.put(67, "C");
            map.put(68, "D");
 
            // Print and display the map object
            System.out.println("Map is " + map);
 
            // Creating a synchronized map object
            // Declaring object of type integer and string
            Map synmap
                = Collections.synchronizedMap(map);
 
            // Print and display the synchronized map
            // elements
            System.out.println("Synchronized map is : "
                               + synmap);
        }
 
        // Catch block to handle the exceptions
        catch (IllegalArgumentException e) {
 
            // Display the exception on the console
            System.out.println(e);
        }
    }
}
输出
Map is {65=A, 66=B, 67=C, 68=D}
Synchronized map is : {65=A, 66=B, 67=C, 68=D}

到目前为止,我们已经讨论了足够多的概念以及通过在程序中实施的内部工作。让我们最后总结出它们之间的差异,以牢牢掌握它们之间的细微差别。

         ConcurrentHashMap                  SynchronizedMap                    HashTable
We will get thread safety without locking the total map object just with a bucket level lock. We will get thread safety by locking the whole map object. We will get thread safety by locking the whole map object
At a time multiple threads are allowed to operate on map objects safely. At a time only one thread is allowed to perform any operation on a map object. At a time one thread is allowed to operate on a map object.
Read operation can be performed without lock but write operation can be performed with bucket level lock. Every read and write operations required total map object  Every read and write operations required total map object 
While one thread iterating map objects the other thread is allowed to modify the map and won’t get ConcurrentModificationException. While one thread iterating map object the other threads are not allowed to modify the map otherwise we will get ConcurrentModificationException While one thread iterating map object the other threads are not allowed to modify the map otherwise we will get ConcurrentModificationException
Iterator of ConcurrentHashMap is fail-safe and won’t raise ConcurrentModificationException Iterator of SynchronizedMap is fail-fast and it will raise ConcurrentModificationException Iterator of HashTable is fail-fast and it will raise ConcurrentModificationException
Null is not allowed for both keys and values. Null is allowed for both keys and values Null is not allowed for both keys and values.
Introduce in java 1.5version Introduce in java 1.2 version Introduce in java 1.0version