Java 同步方法中ConcurrentHashMap的并发级别

Java 同步方法中ConcurrentHashMap的并发级别,java,concurrency,Java,Concurrency,我正在尝试修复内存泄漏问题。堆转储分析表明,ConcurrentHashMap占用了堆内存的约98%。检查代码后发现,ConcurrentHashMap实例化使用的构造函数没有参数。concurrencyLevel的默认配置为16。在这个映射实例化之后,我看到一个同步方法调用,其中数据被放入映射中 我想知道,由于数据只放在synchronized方法中,所以将ConcurrentHashMap的concurrentylevel设置为1安全吗 以下是示例代码段: private volatile

我正在尝试修复内存泄漏问题。堆转储分析表明,
ConcurrentHashMap
占用了堆内存的约98%。检查代码后发现,
ConcurrentHashMap
实例化使用的构造函数没有参数。concurrencyLevel的默认配置为16。在这个映射实例化之后,我看到一个同步方法调用,其中数据被放入映射中

我想知道,由于数据只放在synchronized方法中,所以将ConcurrentHashMap的concurrentylevel设置为1安全吗

以下是示例代码段:

private volatile Map<String, Integer> storeCache;

public void someMethod() {
    storeCache = new ConcurrentHashMap<String, Integer>();
    syncMethod();
}

private synchronized void syncMethod() {
    storeCache.put("Test", 1);
}
私有易失性映射存储缓存;
公共方法(){
storeCache=新的ConcurrentHashMap();
syncMethod();
}
私有同步的void syncMethod(){
storeCache.put(“测试”,1);
}
我想知道,由于数据只放在同步方法中,所以将ConcurrentHashMap的ConcurrentyLevel设置为1安全吗

它当然是安全的,因为它不会导致任何地图损坏。但是,它不会修复内存泄漏。事实上,您可能不想同步对ConcurrentHashMap的访问,因为它已经保证了多线程的安全读写。外部同步将是对CHM的单线程访问,这将消除CHM相对于HashMap的许多好处。如果删除
synchronized
和,可能会获得更好的性能

至于内存泄漏,CHM中的键和值是强引用,这意味着Java垃圾收集器不会收集它们,即使它们不再在代码中的任何其他地方被引用。因此,如果您使用CHM作为临时值的缓存,那么当应用程序不再需要它们时,您需要
.remove()
它们

(如果您想要一个没有强键的ConcurrentMap的语义,那么您无法从框中获得它,但是。)

您可能还需要检查正在映射中的
.put()
键是否已正确实现
.equals()
.hashCode()

我想知道,由于数据只放在同步方法中,所以将ConcurrentHashMap的ConcurrentyLevel设置为1安全吗

它当然是安全的,因为它不会导致任何地图损坏。但是,它不会修复内存泄漏。事实上,您可能不想同步对ConcurrentHashMap的访问,因为它已经保证了多线程的安全读写。外部同步将是对CHM的单线程访问,这将消除CHM相对于HashMap的许多好处。如果删除
synchronized
和,可能会获得更好的性能

至于内存泄漏,CHM中的键和值是强引用,这意味着Java垃圾收集器不会收集它们,即使它们不再在代码中的任何其他地方被引用。因此,如果您使用CHM作为临时值的缓存,那么当应用程序不再需要它们时,您需要
.remove()
它们

(如果您想要一个没有强键的ConcurrentMap的语义,那么您无法从框中获得它,但是。)


您可能还需要检查正在映射的
.put()
键是否已正确实现
.equals()
.hashCode()

CHM不使用任何字节数组,因此这不会造成任何差异。默认的CHM实例使用的空间比字节数组使用的1亿字节少至少5个数量级。我的观点是:CHM内部没有占用98%的空间,而是占用了它所包含的内容。使用并行度1将一无所获。您需要在应用程序代码中查找内存泄漏。有人在地图上添加了太多东西——就这么简单。您总是可以尝试将映射打印到文本文件中。我在参考了此链接后提出了这个问题——关于concurenthashmap的内存泄漏,这里有几个好的方面,在这个问题上:CHM不使用任何字节数组,所以这不会有任何区别。默认的CHM实例使用的空间比字节数组使用的1亿字节少至少5个数量级。我的观点是:CHM内部没有占用98%的空间,而是占用了它所包含的内容。使用并行度1将一无所获。您需要在应用程序代码中查找内存泄漏。有人在地图上添加了太多东西——就这么简单。您可以随时尝试将地图打印到文本文件中。我在参考此链接后提出了这个问题——关于ConcurrentAshmap的内存泄漏,这里有几个好的方面,关于这个问题:它确实有意义。谢谢你,杰森,写了一个详尽的答案。这确实有道理。谢谢你写了一个详细的答案。