使用lambda版本的Callable,ExecutorService submit()无法正常工作

时间:2016-05-31 15:53:28

标签: java future executorservice threadpoolexecutor callable

我正在尝试编写一种同时加载一些模型的机制(使用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)存在问题。

0 个答案:

没有答案