如何完全停止ExecutorService?

时间:2014-04-08 23:39:48

标签: java multithreading executorservice

我在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)

1 个答案:

答案 0 :(得分:0)

你的问题在这里:

for (File file : files) { //... }

我猜您使用ArrayList<File>来保存许多对象文件。但是,数据结构ArrayList不是线程安全的。

ArrayList Java Doc

  

请注意,此实现未同步。如果多个线程同时访问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();
   }