Java ConcurrentHashMap、HashTable和Synchronized Map的区别

Java ConcurrentHashMap、HashTable和Synchronized Map的区别

在这里,我们将一个一个地讨论,然后在充分了解了这三者之后,再来讨论它们的区别。我们将首先讨论ConcurrentHashMap,然后是HashTable,最后是Synchronized Map。让我们先从ConcurrentHashMap开始。

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

语法:

ConcurrentHashMap<K,V> CHM = new  ConcurrentHashMap<>();

上述构造函数创建了一个空的ConcurrentHashMap,具有

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

示例:

// 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<Integer, String> 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);
    }
}

输出

{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中的插入顺序是不保留的,它是基于键的哈希码。不允许键的重复,但值可以重复。键和值都允许有异质的对象。键和值都不允许出现null值,否则我们会得到RunTimeException,即NullPointerException。它实现了Serializable和cloneable接口,但没有实现RandomAccess。它里面的每个方法都是同步的,因此HashTable对象是线程安全的。如果我们的频繁操作是搜索操作,那么HashTable是最好的选择。

语法:

Hashtable<K,V> ht = new Hashtable<>();

上述构造函数创建了一个空的hashtable对象,初始默认容量为11,默认填充率为0.75。其中K是key,V是hashtable的值。

示例:

// 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<Integer, String> 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()方法用于返回一个由指定Map支持的同步(线程安全)Map。这个方法存在于java.util.Collections.Method中。

语法:

public static <K,V> Map<K,V> synchronizedMap(Map<K,V> M)

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

示例:

// Java program to demonstrate synchronizedMap() method
 
// Importing required packages
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<Integer, String> 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<Integer, String> 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 |
| :———————————————————– | :—————————————- | :————————————– |
| 我们将获得线程安全,而不需要锁定整个Map对象,只需要用一个桶级锁。 | 我们将通过锁定整个Map对象来获得线程安全。 | 我们将通过锁定整个Map对象来获得线程安全 |
一次允许多个线程对Map对象进行安全操作。 | 在同一时间,只允许一个线程对一个Map对象进行任何操作。 | 每次允许一个线程对一个Map对象进行操作。
读取操作可以在没有锁的情况下进行,但写入操作可以用桶级锁进行。 | 每一次读和写操作都需要总Map对象 | 每一次读和写操作都需要总Map对象
当一个线程迭代Map对象时,另一个线程被允许修改Map,不会出现ConcurrentModificationException。 | 当一个线程迭代Map对象时,其他线程不允许修改Map,否则我们会得到 ConcurrentModificationException。 | 当一个线程迭代Map对象时,其他线程不允许修改Map,否则我们会得到 ConcurrentModificationException。
ConcurrentHashMap的迭代器是防故障的,不会引发ConcurrentModificationException。 | SynchronizedMap的迭代器是快速失败的,它将引发ConcurrentModificationException | HashTable的迭代器是快速失败的,它将引发ConcurrentModificationException
键和值都不允许为空。 | 键和值都允许为空 | 键和值都不允许为空。
在java 1.5版本中引入 | 在java 1.2版本中引入 | 在java 1.0版本中引入

Python教程

Java教程

Web教程

数据库教程

图形图像教程

大数据教程

开发工具教程

计算机教程