同步方法中ConcurrentHashMap的并发级别

时间:2016-09-07 08:35:10

标签: java concurrency

我正在尝试解决内存泄漏问题。堆转储分析显示ConcurrentHashMap占据98% of heap memory左右。检查代码,结果发现ConcurrentHashMap实例化正在使用没有参数的构造函数。 concurrencyLevel的默认配置是16.在此映射实例化之后,我看到一个同步方法调用,其中数据被放入映射中。

我想知道,由于数据只是在同步方法中放置,将ConcurrentHashMap的concurrencyLevel设置为1是否安全?

以下是示例代码段:

private volatile Map<String, Integer> storeCache;

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

private synchronized void syncMethod() {
    storeCache.put("Test", 1);
}

1 个答案:

答案 0 :(得分:4)

  

我想知道由于数据只是在同步方法中放置,将ConcurrentHashMap的concurrencyLevel设置为1是否安全?

它肯定是安全的,因为它不会导致任何Map损坏。但是,它不会修复你的内存泄漏。实际上,您可能不希望同步对ConcurrentHashMap的访问,这已经保证了来自多个线程的安全读取和写入。外部同步将转向对CHM的单线程访问,这将消除CHM相对于HashMap的许多好处。如果您移除func sceneViewPannedTwoFingers(sender: UIPanGestureRecognizer) { // Get pan distance & convert to radians let translation = sender.translationInView(sender.view!) var xRadians = GLKMathDegreesToRadians(Float(translation.x)) var yRadians = GLKMathDegreesToRadians(Float(translation.y)) // Get x & y radians xRadians = (xRadians / 2) + curXRadians yRadians = (yRadians / 2) + curYRadians // Limit yRadians to prevent rotating 360 degrees vertically yRadians = max(Float(-M_PI_2), min(Float(M_PI_2), yRadians)) // Set rotation values to avoid Gimbal Lock if sender.state == UIGestureRecognizerState.Began { pivotPoint = previewBlock.position } // Rotate around pivot point var position = rotatePlayerAroundPoint(pivotPoint, hAngle: yRadians, vAngle: xRadians) if position.y < 0 { yRadians = directLastTranslationY position = rotatePlayerAroundPoint(pivotPoint, hAngle: yRadians, vAngle: xRadians) } // Set rotation values to avoid Gimbal Lock cameraNode.rotation = SCNVector4(x: 1, y: 0, z: 0, w: yRadians) userNode.rotation = SCNVector4(x: 0, y: 1, z: 0, w: xRadians) // Update <userNode> userNode.position = position // Save value for next rotation if sender.state == UIGestureRecognizerState.Ended { curXRadians = xRadians curYRadians = yRadians } directLastTranslationY = yRadians } private func rotatePlayerAroundPoint(point: SCNVector3, hAngle: Float, vAngle: Float, reach: Float = 8) -> SCNVector3 { let p = point - getSphericalCoords(hAngle, t: vAngle, r: reach) return p } func getSphericalCoords(s: Float, t: Float, r: Float) -> SCNVector3 { return SCNVector3(-(cos(s) * sin(t) * r), sin(s) * r, -(cos(s) * cos(t) * r)) } specify a concurrencyLevel equal to the estimated number of concurrent writes,您可能会获得更好的效果。

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

(如果你想要没有强键的ConcurrentMap的语义,你就不能得到开箱即用的,但是Guava provides a pretty good alternative。)

您可能还想检查您.remove()进入地图的密钥是否已正确实施.put().equals()