0

I have a LinkedBlockingQueue with an arbitrarily picked capacity of 10, and an input file with 1000 lines. I have one ExecutorService-type variable in the main method of the service class that, to my knowledge, first handles--using Executors.newSingleThreadExecutor()--a single thread to call buffer.readline() until file line == null, and then handles--within a loop using Executors.newSingleThreadExecutor()--ten threads to process lines and write them to output files, until !queue.take().equals("Stop"). However, after writing some lines to files, when I am in the debug mode, I see that the capacity of the queue eventually reaches max (10), and the processing threads do not execute queue.take(). All threads are in the running state, but the process halts after queue.put(). What would cause this problem, and is it solvable using some combination of thread-pooling or multiple ExecutorServicehandler variables, instead of a single variable?

Outline for current state of main method in service:

//app settings to get values for keys within a properties file
AppSettings appSettings = new AppSettings();
BlockingQueue<String> queue = new LinkedBlockingQueue<String>(10);

maxProdThreads = 1;
maxConsThreads = 10;

ExecutorService execSvc = null;

for (int i = 0; i < maxProdThreads; i++) {

        execSvc = Executors.newSingleThreadExecutor();

        execSvc.submit(new ReadJSONMessage(appSettings,queue));

    }

    for (int i = 0; i < maxConsThreads; i++) {

        execSvc = Executors.newSingleThreadExecutor();

        execSvc.submit(new ProcessJSONMessage(appSettings,queue));

    }

Reading method code:

buffer = new BufferedReader(new FileReader(inputFilePath));

     while((line = buffer.readLine()) != null){

            line = line.trim();

            queue.put(line);

        }

Processing and Writing code:

while(!(line=queue.take()).equals("Stop")){

        if(line.length() > 10)
        {

            try {
                if(processMessage(line, outputFilePath) == true)
                {
                    ++count;
                }
            } catch (Exception e) {
                e.printStackTrace();
            }               
        }
    }


public boolean processMessage(String line, String outputFilePath){
    CustomObject cO = new CustomObject();
    cO.setText(line);
    writeToFile1(cO,...);
    writeToFile2(cO,...);
}

public void writeOutputAToFile(CustomObject cO,...){
   synchronized(cO){
       ...
       org.apache.commons.io.FileUtils.writeStringToFile(...)
   }
}


public void writeOutputBToFile(CustomObject cO,...){
       synchronized(cO){
           ...
           org.apache.commons.io.FileUtils.writeStringToFile(...)
       }
    }
sda
  • 27
  • 1
  • 5
  • 1
    Please post your read and write code. I get the feeling that you're blocking in there somehow. – Lukas Bradley Sep 26 '17 at 18:21
  • Not your answer, but I'd suggest putting a single `Executors.newCachedThreadPool()` outside your loops and using that. This will allow you to shut all threads down with one call (`exeSvc.shutdown()`) when you're finished. – teppic Sep 26 '17 at 18:41
  • Take a thread dump to see where your threads are blocked. – teppic Sep 26 '17 at 18:46
  • I suspect your consumer tasks have exited (possibly due to a runtime exception), and the "runnable" threads you're looking at in the debugger are idle. – teppic Sep 26 '17 at 18:52
  • Since your problem is obviously with the calls to queue.put and queue.take, wouldn‘t it make sense to include that code in your question? – VGR Sep 26 '17 at 19:04
  • It seems I don't have permission to jvisualvm.exe to access the thread dump. Is there a workaround for this? – sda Sep 26 '17 at 20:25

1 Answers1

0

In the Processing and writing code..ensure that all resources are closed properly..Probably the resources might not be closed properly due to which the thread keeps running and the ExecutorService can not find an idle thread...