未调用 EJB 3.1 单例会话 Bean @PreDestroy 方法
Posted
技术标签:
【中文标题】未调用 EJB 3.1 单例会话 Bean @PreDestroy 方法【英文标题】:EJB 3.1 Singleton Session Bean @PreDestroy method not called 【发布时间】:2015-01-21 17:25:38 【问题描述】:我有一个单例会话 Bean 执行后台任务:
@Singleton
@ConcurrencyManagement(ConcurrencyManagementType.BEAN)
@TransactionManagement(TransactionManagementType.BEAN)
@Startup
public class TaskQueue
private static final Logger LOGGER = Logger.getLogger("TaskQueue");
@Resource
private SessionContext sessionContext;
private final ArrayList<Runnable> tasks = new ArrayList<Runnable>();
private boolean running = false;
@PostConstruct
public void postConstruct()
LOGGER.info("postConstruct");
running = true;
sessionContext.getBusinessObject(TaskQueue.class).taskLoop();
@PreDestroy
public void preDestroy()
LOGGER.info("preDestroy");
running = false;
synchronized (tasks)
tasks.notifyAll();
public void addTask(Runnable r)
synchronized (tasks)
tasks.add(r);
tasks.notifyAll();
@Asynchronous
public void taskLoop()
while (running)
Runnable task;
synchronized (tasks)
LOGGER.info("Fetching next task...");
if (tasks.isEmpty())
try
LOGGER.info("Task queue is empty. Waiting...");
tasks.wait();
LOGGER.info("Resumed");
continue;
catch (InterruptedException e)
break;
task = tasks.remove(0);
LOGGER.info("Executing task...");
task.run();
running = false;
LOGGER.info("Task queue exited");
当我尝试停止模块、取消部署模块或停止服务器时,preDestroy()
方法没有被调用,停止/取消部署过程不会继续。停止服务器的唯一方法是终止 Java 进程。
我正在使用 Jboss EAP 6.0。
我的代码出了什么问题?如何修复它,或者使用 EJB 3.1 进行后台任务队列处理的替代方法是什么?
【问题讨论】:
【参考方案1】:首先,EE 规范禁止管理您自己的线程。您可以这样做,但您应该意识到您违反了规范并了解所有内在含义。相反,您应该考虑利用 Managed Executor 服务 [1]。
话虽如此,我怀疑这里发生的事情是您的 taskLoop 正在锁定对其余单例(包括预销毁)方法的访问。默认情况下,@Singleton 上的所有方法都是@Lock LockType.Write。由于您已经在手动同步,您应该尝试使用 @Lock(LockType.Read) [2]
注释您的 @Singleton 类[1]https://docs.oracle.com/javaee/7/api/javax/enterprise/concurrent/ManagedExecutorService.html
[2]https://docs.oracle.com/javaee/6/api/javax/ejb/LockType.html
【讨论】:
不幸的是,我正在使用 Java EE 6,其中ManagedExecutorService
不可用。任何想法?顺便说一句,这里不需要@Lock,因为我一直在做 Bean Managed Concurrency。
我的问题的最终解决方案是升级到 Java EE 7,并使用 单线程 ExecutorService
和 ManagedThreadFactory
。 @NBW 的建议将我带到了那里,我将其标记为已接受的答案。以上是关于未调用 EJB 3.1 单例会话 Bean @PreDestroy 方法的主要内容,如果未能解决你的问题,请参考以下文章
一篇博客带你拿下吉林大学JAVAEE期末(七:会话Bean)
一篇博客带你拿下吉林大学JAVAEE期末(七:会话Bean)
一篇博客带你拿下吉林大学JAVAEE期末(七:会话Bean)