Java中的ConcurrentHashMap

先决条件: ConcurrentMap

null

这个 ConcurrentHashMap 类是在JDK 1.5所属的 JAVAutil。同时发生的 包,它实现了ConcurrentMap以及可序列化接口。ConcurrentHashMap是HashMap的一个增强,因为我们知道,在应用程序中处理线程时,HashMap不是一个好的选择,因为性能方面的HashMap没有达到标准。

ConcurrentHashMap的要点:

  • ConcurrentHashMap的下划线数据结构为 哈希表 .
  • ConcurrentHashMap类是线程安全的,即多个线程可以在单个对象上操作,而不会出现任何复杂情况。
  • 一次,任何数量的线程都适用于读取操作,而无需锁定HashMap中不存在的ConcurrentHashMap对象。
  • 在ConcurrentHashMap中,根据并发级别将对象划分为若干段。
  • ConcurrentHashMap的默认并发级别为16。
  • 在ConcurrentHashMap中,每次任何数量的线程都可以执行检索操作,但对于对象中的更新,线程必须锁定线程想要操作的特定段。这种锁紧机构被称为 分段锁定或铲斗锁定 。因此,线程一次可以执行16个更新操作。
  • 在ConcurrentHashMap中不能将空对象作为键或值插入。

宣言:

公共类ConcurrentHashMap 扩展抽象映射 实现ConcurrentMap ,可序列化

在这里 K 是键对象类型和 五、 是值对象类型。

ConcurrentHashMap的层次结构

ConcurrentHashMap in Java

它实现了 可序列化 , ConcurrentMap , Map 接口和扩展 抽象地图

ConcurrentHashMap的构造函数

  • 并发级别: 它是同时更新映射的线程数。该实现执行内部大小调整以尝试容纳这么多线程。
  • 荷载系数: 这是一个阈值,用于控制大小调整。
  • 初始容量: 容纳最初由实施提供的一定数量的要素。如果这张地图的容量是10。这意味着它可以存储10个条目。

1.ConcurrentHashMap() :创建具有默认初始容量(16)、负载系数(0.75)和并发级别(16)的新空映射。

ConcurrentHashMap chm=新的ConcurrentHashMap<>();

2.ConcurrentHashMap(int initialCapacity) :创建具有指定初始容量、默认负载系数(0.75)和并发级别(16)的新空映射。

ConcurrentHashMap chm=新的ConcurrentHashMap<>(int initialCapacity);

3.ConcurrentHashMap(int initialCapacity,float loadFactor) :使用指定的初始容量和负载系数以及默认的并发级别(16)创建一个新的空映射。

ConcurrentHashMap chm=新的ConcurrentHashMap<>(int initialCapacity,float loadFactor);

4.ConcurrentHashMap(int initialCapacity,float loadFactor,int concurrentyLevel) :使用指定的初始容量、负载系数和并发级别创建新的空映射。

ConcurrentHashMap chm=新的ConcurrentHashMap<>(int initialCapacity,float loadFactor,int concurrentyLevel);

5.ConcurrentHashMap(Map m) :使用与给定映射相同的映射创建新映射。

ConcurrentHashMap chm=新的ConcurrentHashMap<>(Map m);

例子:

JAVA

// Java program to demonstrate working of ConcurrentHashMap
import java.util.concurrent.*;
class ConcurrentHashMapDemo {
public static void main(String[] args)
{
// create an instance of
// ConcurrentHashMap
ConcurrentHashMap<Integer, String> m
= new ConcurrentHashMap<>();
// Insert mappings using
// put method
m.put( 100 , "Hello" );
m.put( 101 , "Geeks" );
m.put( 102 , "Geeks" );
// Here we cant add Hello because 101 key
// is already present in ConcurrentHashMap object
m.putIfAbsent( 101 , "Hello" );
// We can remove entry because 101 key
// is associated with For value
m.remove( 101 , "Geeks" );
// Now we can add Hello
m.putIfAbsent( 103 , "Hello" );
// We cant replace Hello with For
m.replace( 101 , "Hello" , "For" );
System.out.println(m);
}
}


输出

{100=Hello, 102=Geeks, 103=Hello}

ConcurrentHashMap上的基本操作

1.添加元素

要将映射插入ConcurrentHashMap,我们可以使用 put() putAll() 方法。下面的示例代码解释了这两种方法。

JAVA

// Java program to demonstrate adding
// elements to the ConcurrentHashMap
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
public class AddingElementsToConcuurentHashMap {
public static void main(String[] args)
{
// Creating ConcurrentHashMap
ConcurrentHashMap<String, String> my_cmmap
= new ConcurrentHashMap<String, String>();
// Adding elements to the map
// using put() method
my_cmmap.put( "1" , "1" );
my_cmmap.put( "2" , "1" );
my_cmmap.put( "3" , "1" );
my_cmmap.put( "4" , "1" );
my_cmmap.put( "5" , "1" );
my_cmmap.put( "6" , "1" );
// Printing the map
System.out.println( "Mappings of my_cmmap : "
+ my_cmmap);
// create another concurrentHashMap
ConcurrentHashMap<String, String> new_chm
= new ConcurrentHashMap<>();
// copy mappings from my_cmmap to new_chm
new_chm.putAll(my_cmmap);
// Displaying the new map
System.out.println( "New mappings are: " + new_chm);
}
}


输出

Mappings of my_cmmap : {1=1, 2=1, 3=1, 4=1, 5=1, 6=1}New mappings are: {1=1, 2=1, 3=1, 4=1, 5=1, 6=1}

2.删除元素

要删除映射,我们可以使用 移除(对象键) 类ConcurrentHashmap的方法。如果该键在地图中不存在,则此函数不起任何作用。要清除整个地图,我们可以使用 清除() 方法

JAVA

// Java program to demonstrate removing
// elements from ConcurrentHashMap
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
public class RemoveElementsFromConcurrentHashMap {
public static void main(String[] args)
{
// Creating ConcurrentHashMap
Map<String, String> my_cmmap
= new ConcurrentHashMap<String, String>();
// Adding elements to the map
// using put() method
my_cmmap.put( "1" , "1" );
my_cmmap.put( "2" , "1" );
my_cmmap.put( "3" , "1" );
my_cmmap.put( "4" , "1" );
my_cmmap.put( "5" , "1" );
my_cmmap.put( "6" , "1" );
// Printing the map
System.out.println( "Map: " + my_cmmap);
System.out.println();
// Removing the mapping
// with existing key 6
// using remove() method
String valueRemoved = my_cmmap.remove( "6" );
// Printing the map after remove()
System.out.println(
"After removing mapping with key 6:" );
System.out.println( "Map: " + my_cmmap);
System.out.println( "Value removed: "
+ valueRemoved);
System.out.println();
// Removing the mapping
// with non-existing key 10
// using remove() method
valueRemoved = my_cmmap.remove( "10" );
// Printing the map after remove()
System.out.println(
"After removing mapping with key 10:" );
System.out.println( "Map: " + my_cmmap);
System.out.println( "Value removed: "
+ valueRemoved);
System.out.println();
// Now clear the map using clear()
my_cmmap.clear();
// Print the clea Map
System.out.println( "Map after use of clear(): "
+ my_cmmap);
}
}


输出

Map: {1=1, 2=1, 3=1, 4=1, 5=1, 6=1}After removing mapping with key 6:Map: {1=1, 2=1, 3=1, 4=1, 5=1}Value removed: 1After removing mapping with key 10:Map: {1=1, 2=1, 3=1, 4=1, 5=1}Value removed: nullMap after use of clear(): {}

3.访问元素

我们可以使用 得到() 方法,下面给出了该方法的示例。

JAVA

// Java Program Demonstrate accessing
// elements of ConcurrentHashMap
import java.util.concurrent.*;
class AccessingElementsOfConcurrentHashMap {
public static void main(String[] args)
{
// create an instance of ConcurrentHashMap
ConcurrentHashMap<Integer, String> chm
= new ConcurrentHashMap<Integer, String>();
// insert mappings using put method
chm.put( 100 , "Geeks" );
chm.put( 101 , "for" );
chm.put( 102 , "Geeks" );
chm.put( 103 , "Contribute" );
// Displaying the HashMap
System.out.println( "The Mappings are: " );
System.out.println(chm);
// Display the value of 100
System.out.println( "The Value associated to "
+ "100 is : " + chm.get( 100 ));
// Getting the value of 103
System.out.println( "The Value associated to "
+ "103 is : " + chm.get( 103 ));
}
}


输出

The Mappings are: {100=Geeks, 101=for, 102=Geeks, 103=Contribute}The Value associated to 100 is : GeeksThe Value associated to 103 is : Contribute

4.穿越

我们可以使用 迭代器 接口来遍历集合框架的任何结构。因为迭代器处理一种类型的数据,所以我们使用Entry将这两种不同的类型解析为兼容的格式。然后使用next()方法打印ConcurrentHashMap的元素。

JAVA

// Java Program for traversing a
// ConcurrentHashMap
import java.util.*;
import java.util.concurrent.*;
public class TraversingConcurrentHashMap {
public static void main(String[] args)
{
// create an instance of ConcurrentHashMap
ConcurrentHashMap<Integer, String> chmap
= new ConcurrentHashMap<Integer, String>();
// Add elements using put()
chmap.put( 8 , "Third" );
chmap.put( 6 , "Second" );
chmap.put( 3 , "First" );
chmap.put( 11 , "Fourth" );
// Create an Iterator over the
// ConcurrentHashMap
Iterator<ConcurrentHashMap.Entry<Integer, String> >
itr = chmap.entrySet().iterator();
// The hasNext() method is used to check if there is
// a next element The next() method is used to
// retrieve the next element
while (itr.hasNext()) {
ConcurrentHashMap.Entry<Integer, String> entry
= itr.next();
System.out.println( "Key = " + entry.getKey()
+ ", Value = "
+ entry.getValue());
}
}
}


输出

Key = 3, Value = FirstKey = 6, Value = SecondKey = 8, Value = ThirdKey = 11, Value = Fourth

ConcurrentHashMap方法

  • K –地图上钥匙的类型。
  • 五、 –映射到映射中的值的类型。

方法

描述

清除() 删除此映射中的所有映射。
计算​(K键,双功能重新映射功能) 尝试计算指定键及其当前映射值的映射(如果没有当前映射,则为null)。
计算机​(K键,功能映射功能) 如果指定的键尚未与值关联,则尝试使用给定的映射函数计算其值,并将其输入此映射,除非为null。
计算机呈现​(K键,双功能重新映射功能) 如果指定键的值存在,则尝试在给定键及其当前映射值的情况下计算新映射。
包含​(对象值) 测试某些键是否映射到此表中的指定值。
康纳斯基​(对象键) 测试指定的对象是否是此表中的键。
包含价值​(对象值) 如果此映射将一个或多个键映射到指定值,则返回true。
元素() 返回此表中值的枚举。
入口集() 返回此映射中包含的映射的集合视图。
等于​(对象o) 将指定的对象与此映射进行相等性比较。
弗雷奇​(长并行阈值,双消费者动作) 对每个(键、值)执行给定的操作。
弗雷奇​(长并行阈值,双功能变压器,耗电元件动作) 对每个(键、值)的每个非空转换执行给定的操作。
外国进入​(长平行度阈值,消费者 >行动) 对每个条目执行给定的操作。
外国进入​(长并行性阈值,函数 ,,​? 扩展U>变压器,耗电元件动作) 对每个条目的每个非空转换执行给定的操作。
forEachKey​(长并行阈值,消费者行动) 对每个键执行给定的操作。
forEachKey​(长并行阈值,函数变压器,耗电元件动作) 对每个键的每个非空转换执行给定操作。
前景价值​(长时间并行性阈值,消费者行动) 对每个值执行给定的操作。
前景价值​(长并行阈值,功能变压器,耗电元件动作) 对每个值的每个非空转换执行给定操作。
收到​(对象键) 返回指定键映射到的值,如果此映射不包含该键的映射,则返回null。
getOrDefault​(对象键,V默认值) 返回指定键映射到的值,如果此映射不包含该键的映射,则返回给定的默认值。
hashCode() 返回此映射的哈希代码值,即映射中每个键值对的key和。hashCode()^value。hashCode()。
钥匙() 返回此表中键的枚举。
键集() 返回此映射中包含的键的集合视图。
键集​(V.价值) 返回此映射中键的集合视图,使用给定的公共映射值进行任何添加(即Collection.add(e)和Collection)。addAll(集合))。
mappingCount() 返回映射数。
合并​(K键,V值,双功能重新映射功能) 如果指定的键尚未与(非空)值关联,请将其与给定值关联。
newKeySet() 创建一个由ConcurrentHashMap支持的从给定类型到布尔值的新集合。符合事实的
纽基集​(容量) 创建一个由ConcurrentHashMap支持的从给定类型到布尔值的新集合。符合事实的
放​(K键,V值) 将指定的键映射到此表中的指定值。
普塔尔​(地图m) 将指定映射中的所有映射复制到此映射。
putIfAbsent​(K键,V值) 如果指定的键尚未与值关联,请将其与给定值关联。
减少​(长并行阈值,双功能变压器,双功能减速器) 返回所有(键、值)对的给定转换的累加结果,使用给定的减数器组合值,如果没有,则返回null。
还原试验​(长并行性阈值,双功能 ,,​地图条目 ,,​? 扩展地图。条目 (减速器) 返回使用给定的缩减器合并值累加所有项的结果,如果没有,则返回null。
还原试验​(长并行性阈值,函数 ,,​? 扩展U>变压器,双功能减速器) 返回使用给定的缩减器对所有项进行给定转换以合并值的结果,如果没有,则返回null。
双倍还原​(long parallelism threshold,ToDoubleFunction >变压器、双基、双二进制(减速机) 返回所有项的给定转换的累加结果,使用给定的缩减器组合值,并将给定的基作为标识值。
还原沥青​(long parallelismThreshold,ToIntFunction >变压器,int基,intbinary运算符(减速机) 返回所有项的给定转换的累加结果,使用给定的缩减器组合值,并将给定的基作为标识值。
还原三斯托隆​(长并行性阈值,ToLong函数 >变压器,长基,长二进制(减速机) 返回所有项的给定转换的累加结果,使用给定的缩减器组合值,并将给定的基作为标识值。
reduceKeys​(长并行阈值,双功能减速器) 返回使用给定减缩器组合值累加所有键的结果,如果没有,则返回null。
reduceKeys​(长并行阈值,函数变压器,双功能减速器) 返回使用给定的减缩器对所有键的给定转换进行累加的结果,如果没有,则返回null。
双倍还原​(长并行阈值,ToDoubleFunction变压器,双基,双二进制运算符减速机) 返回所有键的给定转换的累加结果,使用给定的减缩器组合值,并将给定的基作为标识值。
还原基斯托因​(长并行阈值,ToIntFunction变压器,int基,intBinary运算符减速机) 返回所有键的给定转换的累加结果,使用给定的减缩器组合值,并将给定的基作为标识值。
还原基斯托隆​(长并行阈值,ToLong函数变压器,长基,长二进制运算符减速机) 返回所有键的给定转换的累加结果,使用给定的减缩器组合值,并将给定的基作为标识值。
还原双​(长并行阈值,ToDoubleBiFunction变压器,双基,双二进制(减速机) 返回所有(键、值)对的给定转换的累加结果,使用给定的减数器组合值,并将给定的基作为标识值。
还原点​(长并行阈值,ToIntBiFunction变压器,整数基,整数二进制运算符(减速机) 返回所有(键、值)对的给定转换的累加结果,使用给定的减数器组合值,并将给定的基作为标识值。
还原长​(长并行阈值,ToLongBiFunction变压器,长基,长二进制(减速机) 返回所有(键、值)对的给定转换的累加结果,使用给定的减数器组合值,并将给定的基作为标识值。
还原值​(长并行阈值,双功能减速器) 返回使用给定的减缩器合并值累加所有值的结果,如果没有,则返回null。
还原值​(长并行阈值,功能变压器,双功能减速器) 返回所有值的给定转换的累加结果,使用给定的减数器组合值,如果没有,则返回null。
还原值加倍​(长并联阈值,ToDoubleFunction变压器,双基,双二进制运算符减速机) 返回所有值的给定转换的累加结果,使用给定的减数器组合值,并将给定的基作为标识值。
还原值​(长并行阈值,ToIntFunction变压器,整数基,整数二进制运算符减速机) 返回所有值的给定转换的累加结果,使用给定的减数器组合值,并将给定的基作为标识值。
还原值​(长并行阈值,ToLong功能变压器,长基,长二进制运算符减速机) 返回所有值的给定转换的累加结果,使用给定的减数器组合值,并将给定的基作为标识值。
去除​(对象键) 从此映射中删除键(及其对应的值)。
去除​(对象键、对象值) 仅当当前映射到给定值时,才删除键的条目。
代替​(K键,V值) 仅当当前映射到某个值时,才替换键的条目。
代替​(K键,V旧值,V新值) 仅当当前映射到给定值时,才替换键的条目。
搜索​(长并行阈值,双功能搜索功能) 通过对每个(键、值)应用给定的搜索函数返回非null结果,如果没有,则返回null。
搜索条目​(长并行性阈值,函数 ,,​? 扩展U>搜索功能) 通过对每个条目应用给定的搜索函数返回非null结果,如果没有,则返回null。
搜索键​(长并行阈值,函数搜索功能) 通过对每个键应用给定的搜索函数返回非null结果,如果没有,则返回null。
搜索值​(长并行阈值,功能搜索功能) 通过对每个值应用给定的搜索函数返回非null结果,如果没有,则返回null。
toString() 返回此映射的字符串表示形式。
价值观() 返回此映射中包含的值的集合视图。

java类中声明的方法。util。抽象地图

方法

描述

克隆() 返回此AbstractMap实例的浅层副本:不会克隆键和值本身。
isEmpty() 如果此映射不包含键值映射,则返回true。
大小() 返回此映射中的键值映射数。

在java接口中声明的方法。util。同时发生的ConcurrentMap

方法

描述

弗雷奇​(双消费者动作) 对该映射中的每个条目执行给定操作,直到所有条目都已处理或该操作引发异常为止。
替补队员​(双功能功能) 将每个条目的值替换为对该条目调用给定函数的结果,直到处理完所有条目或函数引发异常为止。

必须阅读: HashMap和ConcurrentHashMap的区别

ConcurrentHashMap与Hashtable

散列表

  • 哈希表 是地图数据结构的一个实现
  • 这是一个遗留类,其中所有方法都使用synchronized关键字在哈希表实例上同步。
  • 线程安全,因为它的方法是同步的

ConcurrentHashMap

  • ConcurrentHashMap 实现映射数据结构,并提供哈希表之类的线程安全性。
  • 它的工作原理是将整个哈希表数组划分为段或部分,并允许并行访问这些段。
  • 在hashmap bucket级别,锁定的粒度要细得多。
  • 使用 ConcurrentHashMap 当您的应用程序需要非常高的并发性时。
  • 它是线程安全的,不需要同步整个地图。
  • 在段级或存储桶级锁定完成写操作时,读操作可能会发生得非常快。
  • 在对象级别没有锁定。
  • ConcurrentHashMap不会抛出 ConcurrentModificationException 如果一个线程试图修改它,而另一个线程正在对其进行迭代。
  • ConcurrentHashMap不允许空值,因此密钥在中不能为空 ConcurrentHashMap
  • ConcurrentHashMap不会抛出 ConcurrentModificationException 如果一个线程试图修改它,而另一个线程正在迭代它。
属性 哈希表 ConcurrentHashMap
创造

Map ht=new Hashtable();

Map chm=新的ConcurrentHashMap();

允许空密钥吗?

允许空值吗?

否(不允许空键或值)

线程安全吗?

是的,通过为单独的桶提供单独的锁来确保线程安全,从而提高性能。通过在没有任何阻塞的情况下同时提供读取访问,性能得到进一步提高。
表演

由于同步开销,速度较慢。

比哈希表更快。如果有,ConcurrentHashMap是更好的选择 读的比写的多 .
迭代器 Hashtable使用枚举器迭代Hashtable对象的值。哈希表键和元素方法返回的枚举不是快速失败的。 故障安全迭代器:ConcurrentHashMap提供的迭代器是故障安全的,这意味着它不会抛出 ConcurrentModificationException .

结论:

如果需要线程安全的高并发实现,则建议使用 ConcurrentHashMap 代替 哈希表 .

参考: https://docs.oracle.com/en/java/javase/11/docs/api/java.base/java/util/concurrent/ConcurrentHashMap.html

© 版权声明
THE END
喜欢就支持一下吧
点赞6 分享