I have a file processing program written in Java. The processed data will be put into a LinkedBlockingQueue for their consumers. While I debugged, I stopped all consumers just to make it simple. I noticed that almost every time when the size of that blocking queue reached around 3600ish, everything became slower and slower and then just virtually stopped (the program didn't exit, but no queue size output anymore, and no file got processed) without any OutOfMemoryException. And from the resource monitor, I saw memory level stayed very stable.
Does anybody know what the possible causes could be?
//Here's the code: In Main:
_taskQueue = new BlockingTaskDQueue<StreamQueueItem>();
_fileProcessor = new LogFileProcessor(_taskQueue);
(new Thread(_fileProcessor,LogFileProcessor.myName)).start();
LogFileProcessor:
public class LogFileProcessor implements Runnable {
public static final String myName = ConfigConstants.THREAD_NAME_PREFIX + "FileProcessor";
private BlockingTaskDQueue<StreamQueueItem> mTaskQueue;
private ExecutorService mThreadPool;
//indicate whether the thread pool has been shut down
private boolean mIsEnded = false;
public LogFileProcessor(BlockingTaskDQueue<StreamQueueItem> _taskQueue) {
super();
this.mTaskQueue = _taskQueue;
ThreadFactory namedThreadFactory = new ThreadFactoryBuilder().setNameFormat(ConfigConstants.THREAD_NAME_PREFIX + "FileProc-%d").build();
this.mThreadPool =Executors.newSingleThreadExecutor(namedThreadFactory);
}
@Override
public void run() {
File[] files = null;
//load files in the live_folder
files = ConfigConstants.LIVE_FOLDER.listFiles();
if(files!=null){
for(File f:files){
FileProcTask task = new FileProcTask(f.getName());
mThreadPool.submit(task);
}
}
// Filter which does not accept .tmp files
FileExtensionFilter filter = new FileExtensionFilter("tmp");
while (true) {
// get the non-temp txt file list
files = ConfigConstants.PRODUCTION_FOLDER.listFiles(filter);
if (files.length == 0) {
continue;
}
for (File f : files) {
//move file to the live folder first, then start the task
FileOperator.move(f, ConfigConstants.LIVE_FOLDER);
FileProcTask task = new FileProcTask(f.getName());
mThreadPool.submit(task);
}
}
}
}
Inner FileProcTask class:
class FileProcTask implements Runnable {
private File mFile;
private String mCurrentFileName;
private HashMap<LogReason, List<String[]>> mTableRowMap;
public FileProcTask(String fileName) {
mCurrentFileName = fileName;
mFile = new File(ConfigConstants.LIVE_FOLDER.getAbsolutePath()+ File.separator+fileName);
this.mTableRowMap = new HashMap<LogReason, List<String[]>>();
}
@Override
public void run() {
boolean success = true;
FileInputStream fis;
BufferedReader reader=null;
try {
fis = new FileInputStream(mFile);
reader = new BufferedReader(new InputStreamReader(fis));
String recordItem = reader.readLine(); // ignore the first line of log file
LogReason logReason= LogReason.Unknown;
while(recordItem!=null){
recordItem = reader.readLine();
ConfigConstants.IncRowsScanned();
logReason = this.getLogReason(recordItem);
if(logReason != LogReason.Unknown && logReason != null){
insertToQueue(mCurrentFileName,logReason
,this.getColumns(recordItem));
}
}
} catch (FileNotFoundException e1) {
success = false;
e1.printStackTrace();
} catch (IOException e) {
success = false;
e.printStackTrace();
}finally{
if (reader!=null)
try {
reader.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if(success){
// move file to archive folder
String moveToFolder = FileOperator.getArchiveFolder(mFile);
FileOperator.move(mFile, new File(moveToFolder));
//flush all the rest rows into stream task queue
List<String[]> list_tmp = null;
for (LogReason lr_tmp : mTableRowMap.keySet()) {
list_tmp = mTableRowMap.get(lr_tmp);
if (list_tmp != null && list_tmp.size() > 0) {
synchronized(mTaskQueue){
try {
mTaskQueue.putNewTask(new StreamQueueItem(lr_tmp,
new ArrayList<String[]>(list_tmp)));
list_tmp = null;
System.out.println(mTaskQueue.size());
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
//long now = System.nanoTime();
//ConfigConstants.addToInterval(now-start);
//System.out.println(mCurrentFileName + " process done##");
}else{
System.out.println(mCurrentFileName + " move back##");
FileOperator.move(mFile, ConfigConstants.PRODUCTION_FOLDER);
System.out.format("$$ File %s processing failed, move it back to production folder for re-try",mCurrentFileName);
}
}
private void insertToQueue(String currentFileName, LogReason logreason, String[] columnValues) {
if(columnValues==null)
return;
List<String[]> currentList = mTableRowMap.get(logreason);
if(currentList==null){
currentList = new ArrayList<String[]>();
mTableRowMap.put(logreason, currentList);
}
if (currentList.size() >= ConfigConstants.ROWS_PER_REQUEST) {
// when the current list reach the request quota, put the Bigquery
// Row list into the blocked stream queue.
synchronized(mTaskQueue){
try {
mTaskQueue.putNewTask(new StreamQueueItem(logreason, new ArrayList<String[]>(currentList)));
currentList.clear();
} catch (InterruptedException e) {
e.printStackTrace();
return;
}
}
}
currentList.add(columnValues);
}
}
In the last class, there is a statement of "System.out.println(mTaskQueue.size());". It's where I tried to output the queue size.