我正在尝试将遗留应用程序迁移到当前的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()
时,部署再次被绞死答案 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容器在初始化/部署/引导期间访问并发功能?