在从ExecutorService将它放入Callable(带有其他几个Callable任务)之后,我调用下面的testMethod。我怀疑,map.put()会遇到OutOfMemoryError,因为我试图输入大约2000万个条目。
但是,我无法在控制台中看到错误跟踪。只是线程停止了。我试图捕捉错误(我知道..我们不应该,但我收集的调试)。但是,错误没有被发现。直接进入最后并停止执行..线程静止不动。
private HashMap<String, Integer> testMethod(
String file ) {
try {
in = new FileInputStream(new File(file));
br = new BufferedReader(new InputStreamReader(in), 102400);
for (String line; (line= br.readLine()) != null;) {
map.put(line.substring(1,17),
Integer.parseInt(line.substring(18,20)));
}
System.out.println("Loop End"); // Not executed
} catch(Error e){
e.printStackTrace(); //Not executed
}finally {
System.out.println(map.size()); //Executed
br.close();
in.close();
}
return map;
}
这可能是错误,我在做什么?
编辑:这就是我执行线程的方式。
Callable<Void> callable1 = new Callable<Void>() {
@Override
public Void call() throws Exception {
testMethod(inputFile);
return null;
}
};
Callable<Void> callable2 = new Callable<Void>() {
@Override
public Void call() throws Exception {
testMethod1();
return null;
}
};
List<Callable<Void>> taskList = new ArrayList<Callable<Void>>();
taskList.add(callable1);
taskList.add(callable2);
// create a pool executor with 3 threads
ExecutorService executor = Executors.newFixedThreadPool(3);
List<Future<Void>> future = executor.invokeAll(taskList);
//executor.invokeAll(taskList);
latch.await();
future.get(0);future.get(1); //Added this as per SubOptimal'sComment
但是,这个future.get()没有在控制台中显示OOME。
答案 0 :(得分:2)
提交Callable后,你不应该抛弃未来。
Future future = pool.submit(callable);
future.get(); // this would show you the OOME
示例基于请求者的信息来演示
public static void main(String[] args) throws InterruptedException, ExecutionException {
Callable<Void> callableOOME = new Callable<Void>() {
@Override
public Void call() throws Exception {
System.out.println("callableOOME");
HashMap<String, Integer> map = new HashMap<>();
// some code to force an OOME
try {
for (int i = 0; i < 10_000_000; i++) {
map.put(Integer.toString(i), i);
}
} catch (Error e) {
e.printStackTrace();
} finally {
System.out.println("callableOOME: map size " + map.size());
}
return null;
}
};
Callable<Void> callableNormal = new Callable<Void>() {
@Override
public Void call() throws Exception {
System.out.println("callableNormal");
// some code to have a short "processing time"
try {
TimeUnit.SECONDS.sleep(5);
} catch (InterruptedException ex) {
System.err.println(ex.getMessage());
}
return null;
}
};
List<Callable<Void>> taskList = new ArrayList<>();
taskList.add(callableOOME);
taskList.add(callableNormal);
ExecutorService executor = Executors.newFixedThreadPool(3);
List<Future<Void>> future = executor.invokeAll(taskList);
System.out.println("get future 0: ");
future.get(0).get();
System.out.println("get future 1: ");
future.get(1).get();
}
答案 1 :(得分:1)
尝试捕获Throwable,因为它可能是异常,如IOException或NullPointerException,Throwable捕获除System.exit()之外的所有内容;
另一种可能性是线程没有死亡,而是由于几乎耗尽内存但从不放弃而变得越来越慢。您应该可以通过堆栈转储或在运行时使用jvisualvm
来查看此内容。
BTW除非所有字符串都长度为16个字符,否则您可能希望调用trim()
来删除字符串中的任何填充。这可以缩短它们并减少使用内存。
我假设您使用的是最新版本的Java 7或8.如果您使用的是Java 6或更早版本,则会使用更多内存,因为.substring()
不会创建新的基础{{1}保存CPU,但在这种情况下浪费内存。