Java中的ConcurrentHashMap?

发布于 2024-09-01 10:19:38 字数 72 浏览 3 评论 0原文

Java中ConcurrentHashMap有什么用?它有什么好处?它是如何运作的? 示例代码也很有用。

What is the use of ConcurrentHashMap in Java? What are its benefits? How does it work?
Sample code would be useful too.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(6

我早已燃尽 2024-09-08 10:19:38

重点是提供线程安全的 HashMap 实现。多个线程可以读取和写入它,而不会接收到过期或损坏的数据。 ConcurrentHashMap 提供自己的同步,因此您不必显式同步对其的访问。

ConcurrentHashMap 的另一个功能是它提供了 putIfAbsent 方法,如果指定的键不存在,该方法将自动添加映射。考虑以下代码:

ConcurrentHashMap<String, Integer> myMap = new ConcurrentHashMap<String, Integer>();

// some stuff

if (!myMap.contains("key")) {
  myMap.put("key", 3);
}

此代码不是线程安全的,因为另一个线程可以在对 contains 的调用和对 put< 的调用之间添加 "key" 的映射。 /代码>。正确的实现是:

myMap.putIfAbsent("key", 3);

The point is to provide an implementation of HashMap that is threadsafe. Multiple threads can read from and write to it without the chance of receiving out-of-date or corrupted data. ConcurrentHashMap provides its own synchronization, so you do not have to synchronize accesses to it explicitly.

Another feature of ConcurrentHashMap is that it provides the putIfAbsent method, which will atomically add a mapping if the specified key does not exist. Consider the following code:

ConcurrentHashMap<String, Integer> myMap = new ConcurrentHashMap<String, Integer>();

// some stuff

if (!myMap.contains("key")) {
  myMap.put("key", 3);
}

This code is not threadsafe, because another thread could add a mapping for "key" between the call to contains and the call to put. The correct implementation would be:

myMap.putIfAbsent("key", 3);
清风不识月 2024-09-08 10:19:38

ConcurrentHashMap 允许并发访问映射。 HashTables 也提供对映射的同步访问,但整个映射被锁定以执行任何操作。

ConcurrentHashMap 背后的逻辑是整个表没有被锁定,而只是部分[]。每个段管理自己的哈希表。锁定仅适用于更新。在检索的情况下,它允许完全并发。

假设有四个线程同时处理一个容量为 32 的映射,该表被分为四个段,每个段管理一个容量的哈希表。该集合默认维护一个包含 16 个段的列表,每个段用于保护(或锁定)映射的单个存储桶。

在此处输入图像描述

这实际上意味着 16 个线程可以同时修改集合。可以使用可选的 concurrencyLevel 构造函数 参数来增加此并发级别。

public ConcurrentHashMap(int initialCapacity,
                         float loadFactor, int concurrencyLevel)

正如另一个答案所述,ConcurrentHashMap 提供了新方法 putIfAbsent() ,该方法与 put 类似,只是如果键存在,则值不会被覆盖。

private static Map<String,String> aMap =new ConcurrentHashMap<String,String>();

if(!aMap.contains("key"))
   aMap.put("key","value");

新方法也更快,因为它避免了上面的双重遍历contains 方法必须定位段并迭代表以查找键,而 put 方法必须遍历存储桶并放置键。

ConcurrentHashMap allow concurrent access to the map. HashTables too offers synchronized access to map, but your entire map is locked to perform any operation.

The logic behind ConcurrentHashMap is that your entire table is not getting locked, but only the portion[segments]. Each segments manages its own HashTable. Locking is applied only for updates. In case of of retrievals, it allows full concurrency.

Let's take four threads are concurrently working on a map whose capacity is 32, the table is partitioned into four segments where each segments manages a hash table of capacity. The collection maintains a list of 16 segments by default, each of which is used to guard (or lock on) a single bucket of the map.

enter image description here

This effectively means that 16 threads can modify the collection at a single time. This level of concurrency can be increased using the optional concurrencyLevel constructor argument.

public ConcurrentHashMap(int initialCapacity,
                         float loadFactor, int concurrencyLevel)

As the other answer stated, the ConcurrentHashMap offers new method putIfAbsent() which is similar to put except the value will not be overridden if the key exists.

private static Map<String,String> aMap =new ConcurrentHashMap<String,String>();

if(!aMap.contains("key"))
   aMap.put("key","value");

The new method is also faster as it avoids double traversing as above. contains method has to locate the segment and iterate the table to find the key and again the method put has to traverse the bucket and put the key.

蒲公英的约定 2024-09-08 10:19:38

实际上,最大的功能差异是,当其他人在您使用它时更改它时,它不会引发异常和/或最终损坏。

对于常规集合,如果另一个线程在您访问元素时(通过迭代器)添加或删除元素,它将引发异常。 ConcurrentHashMap 允许他们进行更改并且不会停止您的线程。

请注意,它不会对从一个线程到另一个线程的更改的时间点可见性做出任何类型的同步保证或承诺。 (它有点像读提交数据库隔离,而不是同步映射,后者的行为更像可序列化数据库隔离。(老式行锁定 SQL 可序列化,而不是 Oracle 式多版本可序列化:))

我知道的最常见用途of 是在应用程序服务器环境中缓存不可变的派生信息,其中许多线程可能正在访问相同的事物,并且如果两个线程碰巧计算相同的缓存值并将其放入两次,因为它们交错等,这并不重要(例如,它在 Spring WebMVC 框架中广泛使用,用于保存运行时派生的配置,例如从 URL 到处理程序方法的映射。)

Really the big functional difference is it doesn't throw an exception and/or end up corrupt when someone else changes it while you're using it.

With regular collections, if another thread adds or removes an element while you're access it (via the iterator) it will throw an exception. ConcurrentHashMap lets them make the change and doesn't stop your thread.

Mind you it does not make any kind of synchronization guarantees or promises about the point-in-time visibility of the change from one thread to the other. (It's sort of like a read-committed database isolation, rather than a synchronized map which behaves more like a serializable database isolation. (old school row-locking SQL serializable, not Oracle-ish multiversion serializable :) )

The most common use I know of is in caching immutable derived information in App Server environments where many threads may be accessing the same thing, and it doesn't really matter if two happen to calculate the same cache value and put it twice because they interleave, etc. (e.g., it's used extensively inside the Spring WebMVC framework for holding runtime-derived config like mappings from URLs to Handler Methods.)

药祭#氼 2024-09-08 10:19:38

它可用于记忆:

import java.util.concurrent.ConcurrentHashMap;
public static Function<Integer, Integer> fib = (n) -> {
  Map<Integer, Integer> cache = new ConcurrentHashMap<>();
  if (n == 0 || n == 1) return n;
  return cache.computeIfAbsent(n, (key) -> HelloWorld.fib.apply(n - 2) + HelloWorld.fib.apply(n - 1));
};

It can be used for memoization:

import java.util.concurrent.ConcurrentHashMap;
public static Function<Integer, Integer> fib = (n) -> {
  Map<Integer, Integer> cache = new ConcurrentHashMap<>();
  if (n == 0 || n == 1) return n;
  return cache.computeIfAbsent(n, (key) -> HelloWorld.fib.apply(n - 2) + HelloWorld.fib.apply(n - 1));
};
宛菡 2024-09-08 10:19:38

1.ConcurrentHashMap是线程安全的,即代码一次只能被单个线程访问。

2.ConcurrentHashMap 同步或锁定 Map 的特定部分。为了优化ConcurrentHashMap的性能,根据并发级别将Map划分为不同的分区。这样我们就不需要同步整个Map对象。

3.默认并发级别为16,因此map分为16个部分,每个部分由不同的锁控制,意味着16个线程可以操作。

4.ConcurrentHashMap不允许NULL值。所以 ConcurrentHashMap 中的 key 不能为 null。

1.ConcurrentHashMap is thread-safe that is the code can be accessed by single thread at a time .

2.ConcurrentHashMap synchronizes or locks on the certain portion of the Map . To optimize the performance of ConcurrentHashMap , Map is divided into different partitions depending upon the Concurrency level . So that we do not need to synchronize the whole Map Object.

3.Default concurrency level is 16, accordingly map is divided into 16 part and each part is governed with a different lock that means 16 thread can operate.

4.ConcurrentHashMap does not allow NULL values . So the key can not be null in ConcurrentHashMap .

国粹 2024-09-08 10:19:38

大家好,今天我们讨论了 ConcurrentHashMap。
什么是ConcurrentHashMap?

ConcurrentHashMap是java 1.5中引入的一个类,它实现了ConcurrentMap以及Serialized接口。 ConcurrentHashMap是对HashMap在处理多个Theading时的增强。
我们知道,当应用程序具有多线程时,HashMap 不是一个好的选择,因为会出现性能问题。

ConcurrentHashMap有一些关键点。

  • ConcurrentHashMap 的底层数据结构是 HashTable。
  • ConcurrentHashMap 是一个类,该类是线程安全的,这意味着多个线程可以访问单个线程对象,没有任何复杂性。
  • ConcurretnHashMap 对象根据并发级别分为多个段。
  • ConcurrentHashMap的默认并发级别是16。
  • 在ConcurrentHashMap中,任意数量的Thread都可以执行检索操作,但是对于对象的更新,Thread必须锁定线程想要操作的特定Segment。
  • 这种类型的锁定机制称为段锁定或桶锁定。
  • 在 ConcurrentHashMap 中,一次执行 16 个更新操作。
  • ConcurrentHashMap 中不可能插入空值。

这里是 ConcurrentHashMap 的构造。

  1. ConcurrentHashMap m=new ConcurrentHashMap();:创建一个新的空映射,默认初始容量 (16)、负载因子 (0.75) 和并发级别 (16) .

  2. ConcurrentHashMap m=new ConcurrentHashMap(int initialCapacity);:创建一个具有指定初始容量、默认负载因子 (0.75) 和并发级别 (16) 的新的空映射。

  3. ConcurrentHashMap m=new ConcurrentHashMap(int initialCapacity, float loadFactor);:
    创建一个具有指定初始容量和负载因子以及默认并发级别 (16) 的新的空映射。

  4. ConcurrentHashMap m=new ConcurrentHashMap(int initialCapacity, float loadFactor, int concurrencyLevel);:创建一个具有指定初始容量、负载因子和并发级别的新的空映射。

    ConcurrentHashMap

  5. ConcurrentHashMap m=new ConcurrentHashMap(Map m);:创建一个与给定映射具有相同映射的新映射。

    ConcurrentHashMap m=new ConcurrentHashMap(Map m)

ConcurretHashMap 有一个名为 putIfAbsent(); 的方法,该方法防止存储重复的键,请参考下面的示例。

    import java.util.concurrent.*; 

     class ConcurrentHashMapDemo { 
     public static void main(String[] args) 
     { 
         ConcurrentHashMap m = new ConcurrentHashMap(); 
          m.put(1, "Hello"); 
          m.put(2, "Vala"); 
          m.put(3, "Sarakar"); 

         // Here we cant add Hello because 1 key 
         // is already present in ConcurrentHashMap object 

            m.putIfAbsent(1, "Hello"); 

         // We can remove entry because 2 key 
         // is associated with For value 

            m.remove(2, "Vala"); 

        // Now we can add Vala

            m.putIfAbsent(4, "Vala"); 


            System.out.println(m); 
      } 
}  

Hello guys today we discussed the ConcurrentHashMap.
What is ConcurrentHashMap?

ConcurrentHashMap is a class it introduce in java 1.5 which implements the ConcurrentMap as well as the Serializable interface. ConcurrentHashMap is enhance the HashMap when it dealing with multiple Theading.
As we know when the application has multiple threading HashMap is not a good choice because performance issue occurred.

There are the some key point of ConcurrentHashMap.

  • Underling data structure for ConcurrentHashMap is HashTable.
  • ConcurrentHashMap is a class, That class is thread safe, it means multiple thread can access on a single thread object without any complication.
  • ConcurretnHashMap object is divided into number of segment according to the concurrency level.
  • The Default Concurrency-level of ConcurrentHashMap is 16.
  • In ConcurrentHashMap any number of Thread can perform the retrieval operation,But for updation in object Thread must lock the particular Segment in which thread want to operate.
  • This type of locking mechanism is known as Segment-Locking OR Bucket-Locking.
  • In ConcurrentHashMap the 16 updation operation perform at a time.
  • Null insertion is not possible in ConcurrentHashMap.

Here are the ConcurrentHashMap construction.

  1. ConcurrentHashMap m=new ConcurrentHashMap();:Creates a new, empty map with a default initial capacity (16), load factor (0.75) and concurrencyLevel (16).

  2. ConcurrentHashMap m=new ConcurrentHashMap(int initialCapacity);:Creates a new, empty map with the specified initial capacity, and with default load factor (0.75) and concurrencyLevel (16).

  3. ConcurrentHashMap m=new ConcurrentHashMap(int initialCapacity, float loadFactor);:
    Creates a new, empty map with the specified initial capacity and load factor and with the default concurrencyLevel (16).

  4. ConcurrentHashMap m=new ConcurrentHashMap(int initialCapacity, float loadFactor, int concurrencyLevel);:Creates a new, empty map with the specified initial capacity, load factor and concurrency level.

  5. ConcurrentHashMap m=new ConcurrentHashMap(Map m);:Creates a new map with the same mappings as the given map.

ConcurretHashMap has one method named is putIfAbsent(); That method is prevent to store the duplicate key please refer the below example.

    import java.util.concurrent.*; 

     class ConcurrentHashMapDemo { 
     public static void main(String[] args) 
     { 
         ConcurrentHashMap m = new ConcurrentHashMap(); 
          m.put(1, "Hello"); 
          m.put(2, "Vala"); 
          m.put(3, "Sarakar"); 

         // Here we cant add Hello because 1 key 
         // is already present in ConcurrentHashMap object 

            m.putIfAbsent(1, "Hello"); 

         // We can remove entry because 2 key 
         // is associated with For value 

            m.remove(2, "Vala"); 

        // Now we can add Vala

            m.putIfAbsent(4, "Vala"); 


            System.out.println(m); 
      } 
}  
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文