Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/393.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/multithreading/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 使用ConcurrentHashMap和AtomicLong似乎会导致内存泄漏,但不确定原因_Java_Multithreading_Concurrency_Memory Leaks - Fatal编程技术网

Java 使用ConcurrentHashMap和AtomicLong似乎会导致内存泄漏,但不确定原因

Java 使用ConcurrentHashMap和AtomicLong似乎会导致内存泄漏,但不确定原因,java,multithreading,concurrency,memory-leaks,Java,Multithreading,Concurrency,Memory Leaks,问题:我的代码有内存泄漏,我没有看到它 期望的结果:我希望有人检查我的代码,并就内存泄漏的位置提供建议 额外积分:如果您能想出一种更好的方法来获取用于死锁检测的线程转储(考虑到下面所述的限制),我将非常有兴趣了解它:) 背景信息:我有一个JVM实例,我一直在尝试诊断一些线程死锁。由于缺少对实例的访问权限,我无法使用JConsole或VisualVM执行此操作,因此我只能在死锁发生时尝试将线程转储写入日志 我选择使用ConcurrentHashMap,其中String是线程名称,Long是最后知道

问题:我的代码有内存泄漏,我没有看到它

期望的结果:我希望有人检查我的代码,并就内存泄漏的位置提供建议

额外积分:如果您能想出一种更好的方法来获取用于死锁检测的线程转储(考虑到下面所述的限制),我将非常有兴趣了解它:)

背景信息:我有一个JVM实例,我一直在尝试诊断一些线程死锁。由于缺少对实例的访问权限,我无法使用JConsole或VisualVM执行此操作,因此我只能在死锁发生时尝试将线程转储写入日志

我选择使用
ConcurrentHashMap
,其中
String
是线程名称,
Long
是最后知道的活动的时间戳。该应用程序是一个Spring Boot应用程序,映射位于启动时创建的配置
Bean

当我在本地运行代码时,我看到我感兴趣的13个线程的名称被添加到映射中(实际上我只对13个线程中的1个感兴趣,但它们都是由应用程序具有的依赖项创建的,并且在功能上是相关的)。当我在本地运行时,我从未看到映射的大小增长超过13个条目,而且我没有理由认为在目标JVM实例中会出现这种情况。不过,在将代码移动到JVM实例中之后,人们注意到内存一直在缓慢增长。我已经删除了代码,但是我看不到内存泄漏的地方

下面的
updateObjectLivelity
方法设置为所有13个线程每秒调用一次。因此,只要其中至少有一个是活动的,该方法就会运行。然后,每5分钟检查一次映射,查看在过去5分钟内是否有任何东西没有更新其时间戳,如果是,则运行线程转储代码

下面是课堂:

class ObjectLivelinessMonitor {

    private static final long FIVE_MINS_IN_MILLIS = 300000;

    private final ConcurrentHashMap<String, Long> nameOfThreadAndTimeStampOfLastActivity;
    private final Consumer<Map.Entry<String, Long>> handlerWhenUnlivelinessDetected;
    private final AtomicLong timeStamp;

    ObjectLivelinessMonitor(final Consumer<Map.Entry<String, Long>> handlerWhenUnlivelinessDetected) {
        this.nameOfThreadAndTimeStampOfLastActivity = new ConcurrentHashMap<>();
        this.handlerWhenUnlivelinessDetected = handlerWhenUnlivelinessDetected;
        this.timeStamp = new AtomicLong(System.currentTimeMillis());
    }

    void updateObjectLiveliness(final String nameOfThread) {
        final long currentTime = System.currentTimeMillis();
        nameOfThreadAndTimeStampOfLastActivity.put(nameOfThread, currentTime);
        if((timeStamp.get() + FIVE_MINS_IN_MILLIS) < currentTime) {
            timeStamp.set(currentTime);
            for(final Map.Entry<String, Long> entry : nameOfThreadAndTimeStampOfLastActivity.entrySet()) {
                final long howLongAgoWasLastKnownActivity = currentTime - entry.getValue();
                if(howLongAgoWasLastKnownActivity > FIVE_MINS_IN_MILLIS) {
                    this.handlerWhenUnlivelinessDetected.accept(entry);
                }
            }
        }
    }
}
类ObjectLiveLinesMonitor{
私人静态最终长5分钟(单位:毫)=300000;
private final ConcurrentHashMap剩余活动的线程和时间戳名称;
未检测到LiveLines时的专用最终用户句柄;
私有最终原子长时间戳;
ObjectLiveLinesMonitor(未检测到LiveLines时的最终使用者句柄){
this.nameofthereadandtimestampoflastactivity=new ConcurrentHashMap();
this.handlerWhenLiveLinesDetected=handlerWhenLiveLinesDetected;
this.timeStamp=new AtomicLong(System.currentTimeMillis());
}
void updateObjectLiveity(读取的最终字符串名){
最终长currentTime=System.currentTimeMillis();
name of theread和timestampoflastactivity.put(name of theread,currentTime);
if((timeStamp.get()+五分钟(单位:毫秒)5分钟(单位:毫秒)){
此.handler在未检测到LiveLines时接受(条目);
}
}
}
}
}
下面是线程转储代码:

final Consumer<Map.Entry<String, Long>> handlerWhenUnlivelinessDetected = 
    (final Map.Entry<String, Long> entry) -> {
        final String threadDump = Arrays.stream(ManagementFactory.getThreadMXBean()
                .dumpAllThreads(true, true))
                .map(ThreadInfo::toString)
                .collect(Collectors.joining("\n"));
        logger.error(entry.getKey() + " has been inactive for " + entry.getValue() + " millis: " + threadDump);
};
final Consumer handler当未检测到LiveLines时=
(最终地图。条目)->{
最后一个字符串threadDump=Arrays.stream(ManagementFactory.getThreadMXBean()
.dumpAllThreads(true,true))
.map(ThreadInfo::toString)
.collect(收集器.加入(“\n”));
logger.error(entry.getKey()+”对于“+entry.getValue()+”毫秒:”+threadDump)一直处于非活动状态;
};

我假设我的错误在我使用
ConcurrentHashMap
AtomicLong
时的某个地方,但在在线阅读文档并查找这两个类的源代码之后,我看不出我做错了什么。

根据线程的活动性进行活动性检查是很奇怪的。当没有线程调用updateObjectLiveity时,您永远不会注意到。此外,您没有告诉线程名称来自何处。对于标准线程池执行器,线程可能会在不活动时终止,并在需要时创建新线程。因此,最多仍有13个线程,但您可能会遇到诸如
“thread-14”
“thread-15”
等名称。但既然您可以访问MX bean,那么调用
findDeadlockedThreads()
和/或
findMonitorDeadlockedThreads()
?@Holger只要13个线程中的一个处于活动状态,该方法就会运行。如果所有人都死了,就会发出警报。线程名称由依赖项设置,在本地运行时,我看到一致的命名,与“-15”完全不同。线程是实现
Runnable
的类,它们的实例被添加到
java.util.concurrent.ThreadFactory
。我会尝试使用你推荐的方法。鉴于没有其他人对我的问题做出回应,我认为我对CCM和AtomicLong的使用没有明显的问题,因此这个问题可能是我不知道的其他问题。谢谢,有一个取决于线程的活跃度的活跃度检查是很奇怪的。当没有线程调用updateObjectLiveity时,您永远不会注意到。此外,您没有告诉线程名称来自何处。对于标准线程池执行器,线程可能会在不活动时终止,并在需要时创建新线程。因此,最多仍有13个线程,但您可能会遇到诸如
“thread-14”
“thread-15”
等名称。但是既然您可以访问MX bean,那么调用
findDeadl怎么样