使用ManagedExecutorService

时间:2017-04-04 06:21:24

标签: java-ee websphere-liberty java-ee-7

我正在尝试将遗留应用程序迁移到当前的jee 7标准。

在应用程序部署/引导期间,我们通过启动servlet初始化一些缓存。在部署过程中,很少有缓存被其他应用程序组件使用。这些在遗留应用程序中按顺序初始化。我试图引入多线程来并行初始化所有缓存。所以我使用ManagedExecutorService并提交任务。提交任务后,部署将持续一段时间并无限期停止。以下是我的代码

for(Cacheable cacheable: cacheableApps.values()) {
    mes.submit(new Runnable(){
        public void run() {
            cacheable.initialize();
        }
    });
}

我也尝试过使用ManagedExecutorService.execute(Runnable)和ManagedExecutorService.submit(Callable)而没有运气。

此外,我尝试调用ManagedExecutorService.invokeAll(Collection)和Future.get(),但此时服务器无限期挂起。

然后我用ManagedThreadFactory替换了ManagedExecutorService,并且线程开始初始化,并且在使用缓存的其他应用程序组件中使用NPE完成部署。这是因为缓存在部署结束时正在初始化。

这个想法是用启动单件ejb替换启动servlet,在多个线程中初始化我的缓存并停止部署过程,直到所有线程都返回,这样就不会抛出NPE并且部署顺利完成。

在使用ManagedThreadFactory时,我尝试暂停部署,如下所示

for(Cacheable cacheable: cacheableApps.values()) {
    RunnableTask task =new RunnableTask(cacheable);
    mtf.newThread(task).start();
    tasks.add(task);
}
int count = 0;
while(count!=tasks.size()) {
    count = 0;
    for(Task task: tasks) {
        if(task.isDone()) {
            count++;
        }
    }
}

public class RunnableTask implements Runnable {
    private boolean done;
    public(Cacheable cacheable) {
        this.cacheable = cacheable;
    }
    public void run() {
        cacheable.initialize();
        done = true;
    }
    public boolean isDone() {
        return done;
    }
}

但是这段代码也无限期地挂断了服务器。因为执行在while循环中时线程尚未启动。线程仅在部署结束时开始。所以上面的代码无效。

为了调试问题,我创建了一个虚拟的restful Web服务并添加了以下代码

Future<String> future = mes.submit(new Callable<String>() {
    public String call() throws Exception {
        Cacheable.STUDENT.getApp().initialize();
        return "successful";
    }
});

return future.get();

这初始化了缓存,Web服务的响应是成功的#34;。

然后我将确切的代码复制到我的启动servlet,并在执行future.get()时再次暂停部署

我想知道缓存代码是否存在问题并删除了呼叫,只是返回&#34;成功&#34;。在调用future.get()

时,部署再次被绞死

2 个答案:

答案 0 :(得分:1)

这听起来像是一个可能的错误。您应该收集服务器线程转储以进一步诊断挂起。挂起服务器时,运行以下命令,

server dump <your-server-name>

完成后,它将输出转储文件的位置,例如

wlp/usr/servers/your-server-name/your-server-name.dump-17.04.04_08.21.56.zip

在zip文件中,会有一个子文件夹,例如dump_17.04.04_08.21.56,文本文件名为ThreadInfoIntrospector.txt

此文件包含服务器中所有活动线程的堆栈。他们中的许多人可能闲着。发布任何正在工作的堆栈(挂起)以进一步分析可能的错误。

答案 1 :(得分:0)

我想我发现了这个问题。相同的代码在ejb中工作正常,而不是在启动servlet或servlet监听器中。

此外,我发现在发送http请求时,相同的代码在常规servlet或restful Web服务中正常工作。它是自由中的错误还是ee规范不允许servlet容器在初始化/部署/引导期间访问并发功能?