首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >使用ManagedExecutorService时,自由无限期挂起

使用ManagedExecutorService时,自由无限期挂起
EN

Stack Overflow用户
提问于 2017-04-04 14:21:24
回答 2查看 413关注 0票数 0

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

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

代码语言:javascript
复制
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时,我尝试停止部署,如下所示

代码语言:javascript
复制
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服务,并添加了以下代码

代码语言:javascript
复制
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()时部署再次挂起

EN

回答 2

Stack Overflow用户

发布于 2017-04-04 21:32:20

这听起来像一个可能的bug。您应该收集服务器线程的转储,以便进一步诊断挂起。当服务器挂起时,执行以下命令:

代码语言:javascript
复制
server dump <your-server-name>

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

代码语言:javascript
复制
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的文本文件

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

票数 1
EN

Stack Overflow用户

发布于 2017-04-04 19:04:22

我想我找到问题所在了。相同的代码在ejb中运行良好,而不是在启动servlet或servlet侦听器中运行。

此外,我还发现,当发送http请求时,相同的代码在常规servlet或restful web服务中工作得很好。它是liberty中的一个bug,还是ee规范不允许servlet容器在初始化/部署/引导过程中访问并发特性?

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/43199688

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档