ExecuterService stopped processing one thread out of two - java

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(...).

Related

How to determine if my task was accepted by thread pool and not rejected?

I have ThreadPoolExecutorService, with core pool size 5 and max pool size 10. Also i have set queue size to 0. So when i try to submit 11 tasks - the last one is rejected. For these case i am using RejectedExecutionHandler. However, from submitter thread i can not determine - my task is submitted or rejected.
Here is code from submitter thread:
public void submitToAsyncExecution(Runnable r) {
Future<Void> task = this.threadPool.submit(r)
//is it possible to use returned future object to find out if my task is rejected or not ?
}
I know - alternative is to omit RejectedExecutionHandler and let rejection exception to be throw, however handler approach is more reasonable in my case.
If I understood correctly, you want the code that is using the Future to receive the RejectedExecutionException and handle it, instead of the code calling submitToAsyncExecution.
I can offer you the following:
public static Future<?> submitToAsyncExecution(Runnable r) {
final ExecutorService s;
try {
return s.submit(r);
} catch (RejectedExecutionException e) {
final CompletableFuture<Void> cf = new CompletableFuture<>();
// You can wrap it or create another exception if needed.
cf.completeExceptionally(e);
return cf;
}
}
It catches the exception and creates a Future from it. Every piece of code using it will receive the exception from the rejection and deal with it.

Java Calling method with timeout [duplicate]

I have submitted a task using executors and I need it to stop after some time (e.g. 5 minutes). I have tried doing like this:
for (Future<?> fut : e.invokeAll(tasks, 300, TimeUnit.SECONDS)) {
try {
fut.get();
} catch (CancellationException ex) {
fut.cancel(true);
tasks.clear();
} catch(ExecutionException ex){
ex.printStackTrace(); //FIXME: gestita con printstack
}
}
But I always get an error: I have a shared Vector that needs to be modified by the tasks and then read by a thread, and even if I stop all the task, if the timeout occurs I get:
Exception in thread "Thread-1" java.util.ConcurrentModificationException
Is there something wrong? How can I stop the tasks submitted that are still working after 5 minutes?
Just because you call cancel() on Future doesn't mean that the task will stop automatically. You have to do some work within the task to make sure that it will stop:
Use cancel(true) so that an interrupt is sent to the task.
Handle InterruptedException. If a function in your task throws an InterruptedException, make sure you exit gracefully as soon as possible upon catching the exception.
Periodically check Thread.currentThread().isInterrupted() if the task does continuous computation.
For example:
class LongTask implements Callable<Double> {
public Double call() {
// Sleep for a while; handle InterruptedException appropriately
try {
Thread.sleep(10000);
} catch (InterruptedException ex) {
System.out.println("Exiting gracefully!");
return null;
}
// Compute for a while; check Thread.isInterrupted() periodically
double sum = 0.0;
for (long i = 0; i < 10000000; i++) {
sum += 10.0
if (Thread.currentThread().isInterrupted()) {
System.out.println("Exiting gracefully");
return null;
}
}
return sum;
}
}
Also, as other posts have mentioned: ConcurrentModificationException can be thrown even if using the thread-safe Vector class, because iterators you obtain from Vector are not thread-safe, and thus need to be synchronized. The enhanced for-loop uses iterators, so watch out:
final Vector<Double> vector = new Vector<Double>();
vector.add(1.0);
vector.add(2.0);
// Not thread safe! If another thread modifies "vector" during the loop, then
// a ConcurrentModificationException will be thrown.
for (Double num : vector) {
System.out.println(num);
}
// You can try this as a quick fix, but it might not be what you want:
synchronized (vector) { // "vector" must be final
for (Double num : vector) {
System.out.println(num);
}
}
The ConcurrentModificationException is coming from your call to tasks.clear() while your Exceutors is iterating over your tasks Vector. What you can try to do is call shutdownNow() on your ExecutorService
The most common case for ConcurrentModificationException is when the vector is being modified at the same time as it is being iterated. Often this will be done in a single thread. You need to hold a lock on the Vector for the whole iteration (and careful not to deadlock).
fut.get() is a blocking call, even after the timeout, you will block until the task is done. If you want to stop as close to the 5 minute mark as possible, you do need to check the interrupt flag, I just recommend you do so using the Thread.isInterrupted() method which preserves the interrupt state. If you want to just stop immediately and don't need to clean any state, then throw an exception which will be caught by the Future and indicated to you as an ExecutionException.
fut.cancel(true) does not do anything as the invokeAll() method has already done this for you.
Unless you use the "tasks" Collection somewhere else, you probably don't need to call clear() on it. This isn't going to be the source of your problem since the invokeAll() method is done with the List by the time you call clear(). But, if you need to start forming a list of new tasks to execute, I suggest you form a new List of tasks, not use an old List of new Tasks.
Unfortunately, I do not have an answer for your problem. I do not see enough information here to diagnose it. Nothing in the code snippet you provided indicates an improper (only unnecessary) use of library classes/methods. Perhaps if you included a full stack trace, instead of the one line error.
Put the fut.cancel(true); in the finally block

How to retrieve and handle exceptions in Java's ExecutorService

I am trying to figure out a way to handle exceptions in a multi-thread setting. I would like to execute certain tasks in parallel, each of which might throw an exception that I need to react to (basically, by putting the failed task back into an execution queue). However, it seems to only way to actually get the exception from the thread is to create a Future and call its get() method. However, this essentially turns the calls into synchronous calls.
Maybe some code will illustrate the point:
ExecutorService executor = Executors.newFixedThreadPool(nThreads);
Task task = taskQueue.poll(); // let's assume that task implements Runnable
try {
executor.execute(task);
}
catch(Exception ex) {
// record the failed task, so that it can be re-added to the queue
}
However, in this case all tasks are launched, but the exceptions don't seem to get caught in this catch block here.
An alternative would be to use a Future instead of a thread and retrieve its result:
try {
Future<?> future = executor.submit(task);
future.get();
}
...
In this case, the exceptions are caught alright in the catch block, but at the price of having to wait until this operation is finished. So, the tasks are executed sequentially and not in parallel, as desired.
What am I missing? How can catch each's tasks Exceptions and react to them?
you could trigger all your tasks within one loop and check/await/retry in another:
Map<Future<?>, Task> futures = new HashMap<Future<?>, Task>()
while(!taskQueue.isEmpty()){
Task task = taskQueue.poll();
Future<?> future = executor.submit(task);
futures.put(future, task);
}
for(Map.Entry<Future<?>, Task> entry : futures.entrySet()){
try {
entry.getKey().get();
}
catch(ExecutionException ex) {
// record the failed task, so that it can be re-added to the queue
// you should add a retry counter because you want to prevent endless loops
taskQueue.add(entry.getValue());
}
catch(InterrupredException ex){
// thread interrupted, exit
Thread.interrupt();
return;
}
}
HTH, Mark

Why is this OutOfMemoryError not showing up when thrown by a Future?

A simple scenario:
private static final ExecutorService executor =
Executors.newCachedThreadPool();
public static void main(String... args) throws InterruptedException, ExecutionException {
Future<byte[]> f = null;
for (int i = 0; i < 10; i++) {
f = executor.submit(new Callable<byte[]>(){
#Override
public byte[] call() {
System.out.println("Starting task.");
try {
return new byte[1500 * 1024 * 1024]; // 1500 mb
}
finally {
System.out.println("Task complete.");
}
}
});
}
// System.out.println(f.get().length);
}
When I run the above code it (allegedly) runs without error.
(Strangely, an OutOfMemoryError is being thrown when I profile this code in NetBeans, but not when I run it normally.)
All 10 "Task complete." messages immediatelly show up, in a time-frame far too short for the byte arrays to be actually allocated.
When I uncomment the last line an ExecutionException is thrown.
I know the code example is kind of absurd...
But why is no exception at all being thrown and how can I make the OutOfMemoryError show up? Do I have to catch it? Would that be a safe operation?
You shouldn't catch Errors - they're intended to noisily crash your program. You should only catch an Exception if a. you're logging it / re-throwing it or b. you're handling it; there's no way for you to handle an OutOfMemoryError, so let it crash your program like it's supposed to.
"Task Complete" is showing up when the Future objects have been allocated, not when they're done with their work - you need to call f.get() on each Future to ensure that it's finished allocating its byte array. The program runs slower when you're profiling it, which allows for more Futures to allocate their byte arrays before the Main method terminates, which in turn allows them to use up all of your heap space.
Change f to an ArrayList of futures (and f = executor.submit to f.add(executor.submit)), then iterate through it and call .get() on all of its futures. That should trigger your OutOfMemoryError without using the profiler.
Main thread will not become automatically aware of exceptions throws by threads.
Previous run method was used which doesn't throw exceptions and you were forced to use uncaughtexceptionhandler.
JDK1.5 onwards futures and callables were introduced. Call method of callables throws exception as well as returns a values. Now to catch the exception thrown by call method you need to call future.get().
So your code is working perfectly.

Future.get() not returning all the results

I am creating, say, 15 Callable tasks, and submitting them:
List<Future<MyResult>> futures = new ArrayList<Future<MyResult>>();
List<MyResult> myResults = new ArrayList<MyResult>();
for(int i = 1; i <= 15; i++){
Callable<MyResult> task = new MyProcessor(//parameters);
Future<MyResult> future = executorService.submit(task);
futures.add(future);//used to iterate over to call get() to collect results in next for loop
}
Then I am collecting the 15 MyResult objects:
for(Future<MyResult> future : futures){
try {
MyResult myResult = future.get();
processorResults.add(myResult);
} catch (InterruptedException e) {
//...
} catch (ExecutionException e) {
//...
}
}
Issue is: Instead of getting ALL 15 MyResult objects back from the get() method, I am sometimes getting less than 15 objects back. Sometime 12 sometimes 10 sometimes even lesser, and sometimes all 15.
I was under the impression that get() method is a blocking call and will wait for ALL 15 threads to get back with respective results, but looks like I miss a few of them and move ahead.
What is it that I am doing wrong? Am I not collecting the results/ waiting for the results correctly? Does this happen when an ERROR is thrown from any of the MyProcessor task?
It could mean that some of your jobs threw an exception. It is hard to tell from your code but you need to do something with ExecutionException other than catching and ignoring it.
Future.get() throws ExecutionException when the Callable you submitted throws a RuntimeException from the call() method. It will only return your MyResult if the method returns normally with return. You can get the exception that was thrown by doing:
} catch (ExecutionException e) {
// account for the throw here, the original exception is in e.getCause()
// log it, count it, or ...
logger.error("Job threw exception: " + e.getCause());
}
I was under the impression that get() method is a blocking call and will wait for ALL 15 threads to get back with respective results,
This is correct. When you call future.get() that will block until the job either finishes -- either by throwing an exception or returning. If the thread that is going the get() is interrupted then the get() throws an InterruptedException which also should be caught and not just ignored.

Categories

Resources