Terry Li
Terry Li

Reputation: 17268

Java main process suspended because of exceptions thrown from threads

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

Answers (3)

aim
aim

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

Graham Griffiths
Graham Griffiths

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

Peter Lawrey
Peter Lawrey

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

Related Questions