我在SO上问了一个问题here,得到了一个解决方案there。但在运行该解决方案后,它似乎无法正常工作。
重新说一下,我正在迭代一堆Java文件并逐一分析它们。我的分析算法可能需要1秒到5-10小时。但是如果它没有在10分钟内完成,我想完成分析。如果程序长时间保持运行,程序也会产生内存不足的异常。
这是我正在使用的代码。
For loop:
for (File file : files)
{
String fileName = file.getName();
String filePath = file.getAbsolutePath();
ExecutorService executor = Executors.newSingleThreadExecutor();
Task ts = new Task(filePath);
Future<String> future = executor.submit(ts);
try {
System.out.println("@@ Started.. " + fileName );
System.out.println(future.get(10, TimeUnit.MINUTES));
System.out.println("@@ Finished!" + fileName);
} catch (TimeoutException e) {
System.out.println("@@ Terminated!" + fileName);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (ExecutionException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
finally{
shutdownAndAwaitTermination(executor, future);
future.cancel(true);
}
}
shutdownAndAwaitTermination(,)方法:
// http://docs.oracle.com/javase/7/docs/api/java/util/concurrent/ExecutorService.html
public static void shutdownAndAwaitTermination(ExecutorService pool, Future<String> futureObj) {
pool.shutdown();
try {
if (!pool.awaitTermination(60, TimeUnit.SECONDS)) {
pool.shutdownNow();
if (!pool.awaitTermination(60, TimeUnit.SECONDS))
{
System.err.println("Pool did not terminate");
}
}
} catch (InterruptedException ie) {
pool.shutdownNow();
Thread.currentThread().interrupt();
}
}
}
任务类:
class Task implements Callable<String> {
String fName = "";
Task(String file)
{
fName = file;
}
@Override
public String call() throws Exception {
while(!Thread.currentThread().isInterrupted())
{
// Long running program on file fName.
}
return "Ready!";
}
}
我遇到以下异常:
@@ Started.. file1.java
@@ Terminated!file1.java
Pool did not terminate
@@ Started.. file2.java
java.util.concurrent.ExecutionException: java.util.ConcurrentModificationException
at java.util.concurrent.FutureTask$Sync.innerGet(FutureTask.java:262)
at java.util.concurrent.FutureTask.get(FutureTask.java:119)
at controller.Controller.main(Controller.java:75)
Caused by: java.util.ConcurrentModificationException
at java.util.ArrayList$Itr.checkForComodification(ArrayList.java:819)
at java.util.ArrayList$Itr.next(ArrayList.java:791)
at iterator.CFGIterator.combineCFGs(CFGIterator.java:137)
at iterator.CFGIterator.setOneCFG(CFGIterator.java:92)
at iterator.CFGIterator.<init>(CFGIterator.java:41)
at cfg.ClassObj.iterator(ClassObj.java:47)
at taintanalyzer.TaintAnalyzer.analyze(TaintAnalyzer.java:196)
at cfg.ClassObj.accept(ClassObj.java:65)
at taintanalyzer.TaintAnalyzer.analyze(TaintAnalyzer.java:348)
at controller.Task.call(Controller.java:140)
at controller.Task.call(Controller.java:1)
at java.util.concurrent.FutureTask$Sync.innerRun(FutureTask.java:334)
at java.util.concurrent.FutureTask.run(FutureTask.java:166)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1145)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:615)
at java.lang.Thread.run(Thread.java:722)
答案 0 :(得分:0)
你的问题在这里:
for (File file : files) { //... }
我猜您使用ArrayList<File>
来保存许多对象文件。但是,数据结构ArrayList
不是线程安全的。
请注意,此实现未同步。如果多个线程同时访问ArrayList实例,并且至少有一个线程在结构上修改了列表,则必须在外部进行同步
您可以尝试使用ArrayList
来处理大型列表并获得性能,而不是CopyOnWriteArrayList
。
编辑:
如果要查看第一个文件完成运行并坚持使用awaiTermination,则需要将timeout参数设置得足够大。
pool.shutdown();
try {
// Wait longer, example 6000 seconds for existing task to terminate
if (!pool.awaitTermination(6000, TimeUnit.SECONDS)) {
pool.shutdownNow();
if (!pool.awaitTermination(6000, TimeUnit.SECONDS))
{
System.err.println("Pool did not terminate");
}
}
} catch (InterruptedException ie) {
pool.shutdownNow();
Thread.currentThread().interrupt();
}