【发布时间】:2015-07-05 23:08:20
【问题描述】:
更新
我已经用其他 SO 用户建议的更新代码更新了这个问题,并将澄清以前存在的任何模棱两可的文本。
更新 #2
我只能访问相关应用程序生成的日志文件。因此,我被限制在日志文件的内容内工作,并且没有超出该范围的解决方案是完全可能的。我会稍微修改一下示例数据。我想指出以下关键变量。
Thread ID - 范围从 0..19 - 一个线程被多次使用。因此ScriptExecThread(2) 可能会在日志中出现多次。
Script - 每个线程都会在特定文件上运行脚本。同样的脚本可能在同一个线程上运行,但不会在同一个线程和文件上运行。
File - 每个Thread ID 在File 上运行一个Script。如果Thread(10) 在myfile.file 上运行myscript.script,则不会再次执行该EXACT 行。使用上述示例的成功示例将是这样的。
--------开始-----
Thread(10) 在 myfile.file 上启动 myscript.script
Thread(10) 在 myfile.file 上完成了 myscript.script
--------结束--------
使用上述示例的不成功示例是:
--------开始-----
Thread(10) 在 myfile.file 上启动 myscript.script
--------结束------
在解决我的查询之前,我将简要介绍所使用的代码和所需的行为。
总结
我目前正在解析大型日志文件(平均需要 100k - 600k 行),并尝试按特定顺序检索某些信息。我已经计算出我的请求背后的布尔代数,它似乎在纸上有效,但在代码上却没有那么多(我一定错过了一些明显的东西)。我想提前通知一下,代码没有经过任何优化或优化,现在我只是想让它工作。
在此日志文件中,您可以看到某些线程在启动但从未完成时挂起。可能的线程 ID 范围的数量。这是一些伪代码:
REGEX = "ScriptExecThread(\\([0-9]+\\)).*?(finished|starting)" //in java
Set started, finished
for (int i=log.size()-1; i >=0; i--) {
if(group(2).contains("starting")
started.add(log.get(i))
else if(group(2).contains("finished")
finished.add(log.get(i)
}
started.removeAll(finished);
搜索挂起的线程
Set<String> started = new HashSet<String>(), finished = new HashSet<String>();
for(int i = JAnalyzer.csvlog.size()-1; i >= 0; i--) {
if(JAnalyzer.csvlog.get(i).contains("ScriptExecThread"))
JUtility.hasThreadHung(JAnalyzer.csvlog.get(i), started, finished);
}
started.removeAll(finished);
commonTextArea.append("Number of threads hung: " + noThreadsHung + "\n");
for(String s : started) {
JLogger.appendLineToConsole(s);
commonTextArea.append(s+"\n");
}
已挂起线程
public static boolean hasThreadHung(final String str, Set<String> started, Set<String> finished) {
Pattern r = Pattern.compile("ScriptExecThread(\\([0-9]+\\)).*?(finished|starting)");
Matcher m = r.matcher(str);
boolean hasHung = m.find();
if(m.group(2).contains("starting"))
started.add(str);
else if (m.group(2).contains("finished"))
finished.add(str);
System.out.println("Started size: " + started.size());
System.out.println("Finished size: " + finished.size());
return hasHung;
}
示例数据
ScriptExecThread(1) 在 afile.xyz 上启动
ScriptExecThread(2) 在 bfile.abc 上启动
ScriptExecThread(3) 在 cfile.zyx 上启动
ScriptExecThread(4) 在 dfile.zxy 上启动
ScriptExecThread(5) 在 efile.yzx 上启动
ScriptExecThread(1) 在 afile.xyz 上完成
ScriptExecThread(2) 在 bfile.abc 上完成
ScriptExecThread(3) 在 cfile.zyx 上完成
ScriptExecThread(4) 在 dfile.zxy 上完成
ScriptExecThread(5) 在 efile.yzy 上完成
ScriptExecThread(1) 在 bfile.abc 上启动
ScriptExecThread(2) 在 dfile.zxy 上启动
ScriptExecThread(3) 在 afile.xyz 上启动
ScriptExecThread(1) 在 bfile.abc 上完成
日志结束
如果你举个例子,你会注意到 2 号和 3 号线程已启动但未能完成(原因不是必需的,我只需要获取线路)。
样本数据
09.08 15:06.53, ScriptExecThread(7),Info,########### 开始
09.08 15:06.54, ScriptExecThread(18),Info,###################### 开始
09.08 15:06.54, ScriptExecThread(13),Info,######## 完成于#########
09.08 15:06.54, ScriptExecThread(13),Info,########## 开始
09.08 15:06.55, ScriptExecThread(9),Info,##### ########完成
09.08 15:06.55, ScriptExecThread(0),Info,####finished in ###########
09.08 15:06.55, ScriptExecThread(19),Info,#### 完成于########
09.08 15:06.55, ScriptExecThread(8),Info,###### 完成于 2777 #########
09.08 15:06.55, ScriptExecThread(19),Info,########## 开始
09.08 15:06.55, ScriptExecThread(8),Info,####### 开始
09.08 15:06.55,ScriptExecThread(0),信息,##########starting
09.08 15:06.55, ScriptExecThread(19),Info,Post ###### 完成于 #####
09.08 15:06.55, ScriptExecThread(0),Info,###### 完成于#########
09.08 15:06.55, ScriptExecThread(19),Info,########## 开始
09.08 15:06.55, ScriptExecThread(0),Info,########### 开始
09.08 15:06.55, ScriptExecThread(9),Info,########## 开始
09.08 15:06.56,ScriptExecThread(1),Info,####### ######## 完成
09.08 15:06.56, ScriptExecThread(17),Info,###### 完成于#######
09.08 15:06.56,ScriptExecThread(17),信息,##################### 开始
09.08 15:06.56, ScriptExecThread(1),Info,########## 开始
目前,代码仅显示整个日志文件,其中行以“starting”开头。当我查看代码时,这有点道理。
我已删除任何我不想显示的多余信息。如果有什么我可能遗漏的,请随时告诉我,我会补充。
【问题讨论】:
-
您的样本中似乎没有 ID 为 3 的线程;您是如何生成该输出的?。
-
@tucuxi - 我提供的数据只是为了让您了解部分日志的外观。实际数据超过 600,000 行
-
此行的目的是什么:
else if (hasFinished && hasStarted)?一行日志是否可以同时包含“开始”和“完成”消息? -
@SashaSalauyou - 不完全是,一行可能都不包含(很少但可能)
-
@Juxhin 再次:这条语句
else if (hasFinished && hasStarted)根据执行逻辑检查j行是否包含线程i的both 消息。