我正在尝试将一个遗留应用程序迁移到当前的JEE7标准。
在应用程序部署/引导过程中,我们通过启动servlet初始化一些缓存。在部署过程中,很少有缓存被其他应用程序组件使用。这些是在遗留应用程序中按顺序初始化的。我正在尝试引入多线程来并行初始化所有缓存。因此,我使用ManagedExecutorService并提交任务。提交任务后,部署将继续一段时间,然后无限期停止。下面是我的代码
for(Cacheable cacheable: cacheableApps.values()) {
mes.submit(new Runnable(){
public void run() {
cacheable.initialize();
}
});
}我还尝试使用ManagedExecutorService.execute(Runnable)和ManagedExecutorService.submit(Callable),但没有成功。
此外,我尝试调用ManagedExecutorService.invokeAll(集合)和Future.get(),但服务器在这一点上无限期地挂起。
然后,我将ManagedExecutorService替换为ManagedThreadFactory,线程开始初始化,并在使用缓存的其他应用程序组件中使用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服务的响应是“成功的”。
然后,我将确切的代码复制到我的启动servlet中,在执行future.get()时部署再次挂起。
我想知道缓存代码是否有问题,然后删除了调用并简单地返回"successful“。调用future.get()时部署再次挂起
发布于 2017-04-04 21:32:20
这听起来像一个可能的bug。您应该收集服务器线程的转储,以便进一步诊断挂起。当服务器挂起时,执行以下命令:
server dump <your-server-name>完成此操作后,它将输出转储文件的位置,例如,
wlp/usr/servers/your-server-name/your-server-name.dump-17.04.04_08.21.56.zip在压缩文件中,将有一个子文件夹,如dump_17.04.04_08.21.56,其中包含一个名为ThreadInfoIntrospector.txt的文本文件
此文件包含服务器中所有活动线程的堆栈。他们中的许多人可能是空闲的。张贴任何正在工作的堆栈(挂起),以进一步分析可能的错误。
发布于 2017-04-04 19:04:22
我想我找到问题所在了。相同的代码在ejb中运行良好,而不是在启动servlet或servlet侦听器中运行。
此外,我还发现,当发送http请求时,相同的代码在常规servlet或restful web服务中工作得很好。它是liberty中的一个bug,还是ee规范不允许servlet容器在初始化/部署/引导过程中访问并发特性?
https://stackoverflow.com/questions/43199688
复制相似问题