我有以下代码:
public class Test {
List<Future> future = new ArrayList<Future>();
public static void main(String args[]) throws Exception {
Adapter b1 = new Adapter();
final ExecutorService threadPool = Executors.newCachedThreadPool();
for(//iterate for number of files) {
while(data exists in file) {
//Call a function to process and update values in db
future.add(threadPool.submit(new Xyz(b1)));
//read next set of data in file;
}
}
try {
for(Future f: future) {
f.get();
}
}
catch(Exception e) {
throw e;
}
}
}
class Xyz implements Runnable {
private Adapter a1;
public Xyz(Adapter al) {
this.a1=a1;
}
@Override
public void run() {
try {
a1.abc();
} catch (Exception e) {
throw new RuntimeException(e);
}
}
}
当文件数为1(循环运行1次)时,代码运行正常。
但是,当文件数量增加时,代码永远不会从future.get()
方法返回。
答案 0 :(得分:1)
只是出于好奇......我需要在某处关闭执行程序吗?
是的,这可能就是问题所在。每个Future.get()
将阻塞,直到相应的任务完成,然后一旦所有任务完成,您的main
线程将退出。但是你的java进程将不退出,因为线程池线程在后台仍处于活动状态。完成后应该关闭执行程序,这很可能是main
方法中的最后一个。
我还注意到你提交的许多任务都包含了相同的 Adapter
实例并且都调用了它的abc()
方法 - 检查那里是否有任何会死锁的内容当在多个线程中同时调用时。
答案 1 :(得分:0)
您的Callable::call
/ Runable::run
未返回。否则相应的未来不会阻止。
额外的executor.shutdown或future.cancel
会让InterruptedException
停止处理您提交的对象的线程,但如果要抓住它,则取决于您。您有责任使您提交的工作停止。
当您向CachedExecutor
提交数千个Callables / Runnables时,它可能会产生如此多的线程,导致您的机器变得如此之慢以至于您认为它需要永远。但你会注意到这一点。
当处理未定义数量的可并行化任务时,我建议使用FixedThreadPool
而不是更多的线程存在cpu核心。
编辑:因此,当您在a1.abc();
设置断点并向前迈出一步时,您可能会发现它永远不会返回。