我正在运行以下代码来显示我的程序的正在运行的线程
public void printTasks() {
System.out.println("get threads start");
for (Thread thread : Thread.getAllStackTraces().keySet()) {
//This block filters the non-java threads running
if (!thread.getThreadGroup().getName().equals("system")) {
System.out.println("hello");
}
}
System.out.println("get threads end");
}
问题在于,有时代码会在打印后立即挂起"让线程启动",我怀疑挂起发生在这一行" Thread.getAllStackTraces()"
注意:我的程序使用线程执行一组任务,因此,它会创建大约70个线程并且挂起是间歇性的,我称之为此方法的每6或7次中只有1个出现问题
我的问题是:
编辑:我使用java 1.8,问题发生在Linux OEL和Windows Server中,在这两种情况下都是间歇性的,软件作为独立的桌面应用程序运行
提前谢谢
答案 0 :(得分:0)
我刚刚发现了问题所在(至少这是我的假设)。
用于检索正在运行的线程的代码遇到了竞争条件。
我的程序正在创建的线程不断变化,有些线程会在非常短的时间内(1秒或更短的时间内)结束
函数Thread.getAllStackTraces()
返回 HashMap 的线程和堆栈跟踪(第a行),然后在下一行(第b行)我试图获取线程的组名
for (Thread thread : Thread.getAllStackTraces().keySet()) { <--- a
if (!thread.getThreadGroup().getName().equals("system")) { <--- b
但线程持续得很少,以至于在第二行到达之前消失了,因此我最终尝试使用无效键从地图中获取值(这是竞争条件)
注意:如果您以前从未体验过这种情况,当您尝试读取不存在的HashMap的值时,您可能最终会等待结果
<强>解决方案强>
在尝试读取其属性
之前,确保线程仍然存在public void printTasks() {
System.out.println("get threads start");
for (Thread thread : Thread.getAllStackTraces().keySet()) {
//This block filters the non-java threads running
if (Thread.getAllStackTraces().containsKey(thread) && //<--new line here
thread.getThreadGroup().getName().equals("system")) {
System.out.println("hello");
}
}
System.out.println("get threads end");
}
第二种方法是尝试获取getAllStackTraces()内容的快照以读取不可变对象
欢迎更好的解决方案,希望这有助于某人