我正在尝试编写一种同时加载一些模型的机制(使用ExecutorService)并在完成所有模型后检索它们的结果:
List<Future<Model>> modelFutures = new LinkedList<Future<Model>>();
ExecutorService executor = Executors.newFixedThreadPool(DEFAULT_THREAD_POOL_SIZE);
List<Model> models = new ArrayList<Model>();
for (ClassifierConfig classifierConfig : classifiers) {
try {
final String modelFileName = classifierConfig.name + ".model";
modelFutures.add(executor.submit(new InitModelTask(MODELS_LOCAL_DIR + SEP + modelFileName)));
} catch (Exception e) {
e.printStackTrace();
}
}
for (Future<Model> modelFuture : modelFutures) {
try {
models.add(modelFuture.get(MAX_REQUEST_TIMEOUT_MILLIS, TimeUnit.MILLISECONDS));
} catch (Exception e) {
System.out.println("Timeout occurred when loading models ");
}
}
executor.shutdown();
return models;
任务类如下:
public class InitModelTask implements Callable<Model> {
private String modelFileName;
public InitModelTask(String modelFileName) {
this.modelFileName = modelFileName;
}
@Override
public Model call() throws Exception {
return WekaModuler.loadModel(modelFileName, Model.class);
}
}
此代码有效。
但是,我希望通过以下列方式调用执行程序的InitModelTask
方法来删除Callable
类并将其转换为内联submit()
,从而使其更加优雅:
modelFutures.add(executor.submit(() -> WekaModuler.loadModel(MODELS_LOCAL_DIR + SEP + modelFileName)));
这通过编译,运行,创建执行程序服务线程池,但是当需要调用实际的可调用时,它就会卡住。
我尝试在WekaModuler::loadModel
内放置一个断点,它永远不会停在那里。
我查看了线程转储,并且线程池中的所有线程都处于RUNNABLE状态并指定了以下堆栈跟踪:
"pool-2-thread-13" #27 prio=5 os_prio=0 tid=0x000000001da52000 nid=0xd78 in Object.wait() [0x0000000021fdf000]
java.lang.Thread.State: RUNNABLE
at com.evercompliant.weka.classifier.EverClassifier$$Lambda$4/1222094219.call(Unknown Source)
at java.util.concurrent.FutureTask.run(FutureTask.java:266)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
at java.lang.Thread.run(Thread.java:745)
内联Callable
和实际Callable
- 实施类之间是否有任何区别?
我必须指出,我尝试使用返回Future<Integer>
的一些虚拟任务来模拟相同的事情,并且一切正常并且符合预期。该发现表明实际域(WekaModuler
)存在问题。