Reputation: 17268
The main process:
int cpus = Runtime.getRuntime().availableProcessors();
ExecutorService executor = Executors.newFixedThreadPool(cpus);
List<Callable<Object>> todo = new ArrayList<Callable<Object>>(lines.size());
for (int r = 0; r < lines.size(); r++) {
String filename = r + 1 + "";
todo.add(Executors.callable(new AppConsole(filename, lines.get(r))));
}
List<Future<Object>> answers = executor.invokeAll(todo);
The AppConsole class implements Runnable and the overriden run method is as follows:
public void run() {
try{
} catch (SecurityException exception) {
exception.printStackTrace();
} catch (FileNotFoundException exception) {
exception.printStackTrace();
} catch (IOException exception) {
exception.printStackTrace();
} catch (SAXException exception) {
exception.printStackTrace();
} catch (Exception exception) {
exception.printStackTrace();
} finally {
if (output != null) {
output.close();
}
}
}
}
The main process is suspended and cannot finish because of a connection timeout exception thrown from one of the threads. Now I can see the cpu usage drops to 0% and the memory consumption keeps at the same level when it got suspended.
Could someone please help me solve this problem? At least, help me make the main process finish?
Upvotes: 0
Views: 516
Reputation: 1493
You just need to add:
executor.shutdown();
This waits when all tasks will be completed and shutdown all threads, application will exit after that. Please see javadoc for newFixedThreadPool:
Creates a thread pool that reuses a fixed number of threads operating off a shared unbounded queue. At any point, at most nThreads threads will be active processing tasks. If additional tasks are submitted when all threads are active, they will wait in the queue until a thread is available. If any thread terminates due to a failure during execution prior to shutdown, a new one will take its place if needed to execute subsequent tasks. The threads in the pool will exist until it is explicitly shutdown.
Upvotes: 0
Reputation: 2216
you could use the alternative version of invokeAll that takes an explicit timeout value :
http://docs.oracle.com/javase/6/docs/api/java/util/concurrent/ExecutorService.html
invokeAll(Collection<? extends Callable<T>> tasks,
long timeout,
TimeUnit unit)
this way you can force all of your tasks to timeout after, say, 30 seconds. Then you can inspect the Futures returned to see which have completed.
Upvotes: 0
Reputation: 533640
Throwing an exception frees up the tasks and the main thread. The ExecutorService treats an Exception throw much like another return value and doesn't have a problem handling it.
The main thread will only block waiting for one of your tasks to complete. I would look at the tasks/threads which are still active to see what they are doing e.g. perhaps they haven't timed out yet.
Upvotes: 3