我正在尝试解决内存泄漏问题。堆转储分析显示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);
}
答案 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()
。