我會採取一次讀取日誌文件並使用HashMap跟蹤請求/響應的方法。地圖鍵將是計數器,地圖值將是請求的日期。要節省內存,請在收到響應時從地圖中刪除項目。使用Java的pattern matching來確定它是一個請求還是響應以及獲取計數器ID和日期。
下面是一個例子:
final static long EXPIRED_MILLIS = 1000 * 10; // ten seconds
final static Pattern REQUEST_PATTERN = Pattern.compile("(.*)(<< \\d{4})(REQUEST COUNTER=\")(\\d)(\")");
final static Pattern RESPONSE_PATTERN = Pattern.compile("(.*)(<< \\d{4})(RESPONSE COUNTER=\")(\\d)(\")");
final static SimpleDateFormat DATE_FORMAT = new SimpleDateFormat("yy/MM/dd-HH:mm:ss.SSS");
List<String> getExpiredCounterList(File file) throws Exception {
Map<String,Long> requestMap = new HashMap<>();
List<String> expiredCounterList = new ArrayList<>();
try(FileReader fileReader = new FileReader(file);
BufferedReader buffReader = new BufferedReader(fileReader))
{
String line;
while((line = buffReader.readLine()) != null) {
Matcher requestMatcher = REQUEST_PATTERN.matcher(line);
if(requestMatcher.matches()) {
addRequestToMap(line, requestMatcher, requestMap);
continue;
}
Matcher responseMatcher = RESPONSE_PATTERN.matcher(line);
if(requestMatcher.matches()) {
String expiredCounter = checkIfExpiredAndRemoveFromMap(line, responseMatcher, requestMap);
if(expiredCounter != null)
expiredCounterList.add(expiredCounter);
}
}
}
return expiredCounterList;
}
void addRequestToMap(String request, Matcher requestMatcher, Map<String,Long> requestMap) {
String counter = getCounter(request, requestMatcher, 4);
long date = getDate(request, requestMatcher, 1);
requestMap.put(counter, date);
}
String checkIfExpiredAndRemoveFromMap(String response, Matcher responseMatcher, Map<String,Long> requestMap) {
String counter = getCounter(response, responseMatcher, 4);
if(requestMap.containKey(counter)) {
long date = getDate(response, responseMatcher, 1);
long elapsedMillis = date - requestMap.remove(counter);
if(elapsedMillis > EXPIRED_MILLIS)
return counter;
}
return null;
}
String getCounter(String line, Matcher matcher, int group) {
return line.substring(matcher.start(group), matcher.end(group));
}
long getDate(String line, Matcher matcher, int group) throws ParseException {
return DATE_FORMAT.parse(line.substring(matcher.start(group), matcher.end(group))).getTime();
}
請注意,您可以爲每個匹配行使用相同的SimpleDateFormat對象,而不是每次都創建一個新對象。 – Berger
只要你沒有多個線程並行處理你的文件!然後每個線程都需要自己的格式化程序。 – GhostCat
在閱讀日誌文件時,我會在列表中記錄我遇到的「請求」。一旦我到達「RESPONSE」行,我會從列表中刪除相應的REQUEST,並檢查延遲是否超過10秒。 – Aaron