I have a list of 40000 records that needs to be processed in a for loop. Since I have a two processor system. I have created a fixedThreadPool like this:
int threads = Runtime.getRuntime().availableProcessors();
ExecutorService service = Executors.newFixedThreadPool(threads);
And divided my ArrayList
into two sublists. For each of these sublists, I have created a Callable
that performs the same function (involves iterating over the sublist and doing some processing) and returns me a Future
object.
I submitted both these Callable
using executorServiceObject.submit(callable)
and added the returned Future
object into my list of Future
objects
Here is my question:
I have written a System.Out.printLn("Processed Item" +item.id) // consider item as the name of reference variable for current iteration
Everything was fine for some time and i could see two threads working simutaneously. But after some time, one of the threads have stopped processing. Only one thread is running. (I know this because i can see on the console that the id's given to thread 2 are not being printed anymore).
Does anyone know how this happened? I mean why ExecutorService stopped running 2nd thread.
Thanks for your help in advance.
Adding sample code as I should have done before:
public List<Output> processInputs(List<Input> inputs)
throws InterruptedException, ExecutionException {
int threads = Runtime.getRuntime().availableProcessors();
ExecutorService service = Executors.newFixedThreadPool(threads);
List<Future<Output>> futures = new ArrayList<Future<Output>>();
for (final Input input : inputs) {
Callable<Output> callable = new Callable<Output>() {
public Output call() throws Exception {
Output output = new Output();
// process your input here and compute the output
return output;
}
};
futures.add(service.submit(callable));
}
service.shutdown();
List<Output> outputs = new ArrayList<Output>();
for (Future<Output> future : futures) {
outputs.add(future.get());
}
return outputs;
Everything was fine for some time and i could see two threads working simultaneously. But after some time, one of the threads have stopped processing. Only one thread is running. (I know this because i can see on the console that the id's given to thread 2 are not being printed anymore).
I suspect that your processing thread has thrown an exception. The Future.get()
method can throw ExecutionException
"if the computation threw an exception".
// the following might throw an exception if the background job threw
outputs.add(future.get());
If there was a NPE, an IOException, etc. thrown by your "process your input" code then that exception is thrown by the Callable
and stored in the Future
so it can be thrown by the get()
method but wrapped in an ExecutionException
. This is useful so the thread that is waiting can get and and handle (log, etc.) the exception thrown by the background thread.
Instead of just having your processInputs(...)
method throw the exception to the caller where it might be getting lost, I'd do something like the following in your while
loop:
try {
outputs.add(future.get());
} catch (InterruptedException ie) {
// always a good pattern if the thread that is waiting was interrupted
Thread.currentThread().interrupt();
return;
} catch (ExecutionException ee) {
// somehow log the error
logger.error("Computation failed to process", ee);
// now continue and get the next future in the list
}
If you don't catch and properly handle that ExecutionException
then the processing exception will also kill the thread that calls processInputs(...)
.