【发布时间】:2015-10-13 01:46:44
【问题描述】:
背景
- 在下面的代码中,创建并启动了“a”线程。
- run 方法包含一个无限循环。
- 在循环中,成员变量“prod”会在每个特定时间间隔后重新分配一个新配置的对象。
-
配置基于一个 json 对象,该对象又使用配置文件创建
public class Producer extends Thread { private long lastReadTime; private long refreshInterval; private String configFile; private JSONObject configJson; private MyProducer prod; public StdInProducer (String filename) throws IOException { this.configFile = filename; this.refreshConfig(); } public void refreshConfig() { this.lastReadTime = System.currentTimeMillis(); this.configJson = new JSONObject(FileUtils.readFileToString(new File(this.configFile), "UTF-8")); this.refreshInterval = this.confJsonObj.optLong("refreshInterval", 86400); this.initializeProducer(configJson); } private void initializeProducer(JSONObject confJsonObj) { //initialise producer using json object values this.prod = // new MyProducer obj with settings from json obj } public void run() { while(true) { long currentTime = System.currentTimeMillis(); if(currentTime - this.lastReadTime > this.refreshInterval*1000) { this.refreshConfig(); } // Rest of the code } } } public static void main(String[] args) { String configFilename = args[0]; Thread t = new Producer(configFilename); t.start(); }
观察
Thread.activeCount()
显示输出为 2
ps -aefL | grep producer | grep -v "grep" | wc -l
显示程序启动时最初运行的 22 个线程。
ps -aefL | grep producer
root 18498 1 18498 0 22 Jul22 ? 00:00:00 /usr/bin/java -cp producer-1.0.jar stdin.producer.Producer stdinConfig.json
root 18498 1 18499 0 22 Jul22 ? 00:00:00 /usr/bin/java -cp producer-1.0.jar stdin.producer.Producer stdinConfig.json
root 18498 1 18500 0 22 Jul22 ? 00:01:55 /usr/bin/java -cp producer-1.0.jar stdin.producer.Producer stdinConfig.json
root 18498 1 18501 0 22 Jul22 ? 00:01:55 /usr/bin/java -cp producer-1.0.jar stdin.producer.Producer stdinConfig.json
(由于空间限制,只显示少数行)
在程序初始运行大约 2 个月后观察到问题,观察到盒子上的线程数约为 70(使用 ps 命令),“top”显示 VIRT 内存使用量为 12 GB。
重新启动程序后,第 23 个线程被添加到上面的列表中 一天(24 小时)后的线程,增加虚拟内存。那么问题就在那里,需要找出原因吗?
问题
程序创建了多少线程?
ps 命令显示这么多“线程”的原因是什么?
为什么线程的数量会随着时间的推移而增加,从而导致内存使用量增加?
【问题讨论】:
-
您是否使用 JProfile 或 VisualVM 之类的工具进行了仔细检查,以确保您的 bash 命令执行您认为的操作?
-
这是一个 Amazon EC2 盒子。我现在知道是否可以安装类似的东西来仔细检查。我尝试在 mac 上模拟类似的东西并检查
-
其中一个线程是您的 main() 线程,其中之一是您的主线程创建的线程。其余的是 JVM 的实现细节。 Java 语言规范或 JVM 规范中没有任何内容说明会有多少。确切的数字在不同的 JVM、不同的操作系统上可能不同,并且可能在进程生命周期的不同时间。
-
是的,我知道数字 2。但数字 22 或 ~70 是我所关心的。此外,这大约 70 个是在该计划最初启动后的不同日期生成的,其中一些已经超过一个月没有消失。
-
JVisualm 是检验这一点的唯一方法。附加到活进程,你会看到有多少线程以及它们在做什么
标签: java multithreading memory memory-leaks