由于从线程抛出的异常,Java主进程被挂起

时间:2013-08-06 08:33:10

标签: java multithreading

主要过程:

            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);

AppConsole类实现了Runnable,而overriden run方法如下:

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();
            }
        }
  }

}

由于从其中一个线程抛出连接超时异常,主进程被挂起并无法完成。现在我可以看到cpu使用率下降到0%,内存消耗在挂起时保持在同一级别。

有人可以帮我解决这个问题吗?至少,帮我完成主要工艺?

3 个答案:

答案 0 :(得分:3)

抛出异常会释放任务和主线程。 ExecutorService将异常抛出视为另一个返回值,并且处理它时没有问题。

主线程只会阻止等待您的某个任务完成。我会查看仍处于活动状态的任务/线程,看看他们正在做什么,例如也许他们还没有超时。

答案 1 :(得分:0)

你只需要添加:

executor.shutdown();

等待所有任务完成并关闭所有线程后,应用程序将在此之后退出。 请参阅newFixedThreadPool的javadoc:

  

创建一个重用固定数量的线程的线程池   关闭共享的无界队列。在任何时候,最多nThreads线程   将是主动处理任务。如果提交了其他任务   当所有线程都处于活动状态时,它们将在队列中等待直到a   线程可用。如果任何线程由于故障期间终止而终止   在关机之前执行,如果需要,新的将取代它   执行后续任务。池中的线程将一直存在   它是明确关闭的。

答案 2 :(得分:0)

你可以使用带有显式超时值的invokeAll的替代版本:

http://docs.oracle.com/javase/6/docs/api/java/util/concurrent/ExecutorService.html

invokeAll(Collection<? extends Callable<T>> tasks,
                          long timeout,
                          TimeUnit unit)
通过这种方式,您可以强制所有任务在30秒后超时。然后你可以检查返回的期货,看看哪些已经完成。