【发布时间】:2014-05-06 18:13:30
【问题描述】:
我需要将现有的 spring 应用程序与自定义的 elasticsearch 河集成,ES 河使用 Google Guice 管理它们的依赖关系并在它们自己的线程集中运行。
我创建了一个简单的类,它返回对 spring 上下文的静态引用,并配置了一个从 spring 上下文返回对象的 Guice 模块。为了确保 guice 线程和 spring 线程之间的正确同步,我使用了在上下文完全初始化后释放的CountDownLatch。这是一些代码
public class GuiceSpringIntegrator implements ApplicationListener<ContextRefreshedEvent> {
private static ApplicationContext context;
private static final CountDownLatch contextLatch = new CountDownLatch(1);
@Override public void onApplicationEvent(ContextRefreshedEvent event) {
try {
// check some stuff in context
} finally {
log.debug("Setting application context as static field of {}", getClass().getSimpleName());
GuiceSpringIntegrator.context = event.getApplicationContext();
log.info("Releasing latch for application context");
contextLatch.countDown();
}
}
public static ApplicationContext getApplicationContext() {
if (null == context) {
log.info("ApplicationContext not yet initialized, wait for it in thread {}", Thread.currentThread().getName());
Uninterruptibles.awaitUninterruptibly(contextLatch); <-- !!! SPRING INITIALIZATION CODE HANGS HERE
log.debug("Returning application context since now context is initialized");
Preconditions.checkState(context != null, "ApplicationContext should have been initialized properly");
}
return context;
}
}
这是使用上述类的guice模块
/**
* Guice module configuration
*/
public class ElasticSearchModule extends AbstractModule {
@Override
protected void configure() {}
@Provides @Singleton TaskScheduler getSchedulerInstance() {
return GuiceSpringIntegrator.getApplicationContext().getBean(TaskScheduler.class);
}
// and so on...
}
但是,当我启动应用程序(尤其是在快速服务器上)时,应用程序偶尔会挂在上面代码中标记的行。我仔细检查了导致#getApplicationContext() 方法调用的每个代码路径,它们(应该)被guice调用,所以最终应该释放闩锁并且代码应该继续。
- 有没有更好的方法来处理这种情况?
- 有没有办法检查我是否在 spring 初始化代码中,比如isEventDispatchThread for swing?如果我以某种方式从 Spring 初始化代码中调用
#getApplicationContext,我想使用该代码进行跟踪? - 为什么在上下文初始化实际完成之前似乎调用了
#onApplicationEvent? - 有关如何调试此问题的任何提示?我正在阅读有关在实时服务器上进行线程转储的信息,对吗?
【问题讨论】:
-
如果您可以重现死锁,分析堆栈跟踪(例如,
kill -3)确实会有所帮助。顺便说一句,你看到你的日志条目了吗?你确定调用了 onApplicationEvent 吗? -
@PhilippClaßen 我将尝试使用
kill -3我现在正在寻找有关此的更多信息。发生死锁的时候是因为onApplicationEvent没有被调用,所以我的想法是一些配置好的spring bean间接调用getApplicationContext整个事情挂了。
标签: java multithreading spring deadlock guice