11

我目前正在研究一些在没有考虑应用服务器的情况下开发的旧 Java 代码。它基本上是一堆带有输入接口和输出接口的“黑盒代码”。“黑匣子”类中的所有内容都是包含状态的静态数据结构,这些状态以定时间隔(每 10 秒)通过算法。黑盒是从一个 main 方法启动的。

为了让我自己轻松,我正在考虑将“黑匣子”设为单例。基本上,任何想要访问黑匣子内部逻辑的人都会得到相同的实例。这将允许我使用消息驱动 bean 作为黑盒的输入,并使用某种 JMS Publisher 作为黑盒的输出。

这是多么糟糕的想法?有小费吗?

不过,我主要担心的问题之一是“黑盒”代码中可能存在我不知道的线程。

EJB 中是否存在诸如“应用程序范围的对象”之类的东西?

注意:我使用的是 Glassfish

4

11 回答 11

15

如果使用简单的单例,一旦进入集群环境,就会遇到问题

在这种情况下,您在多个 JVM 上有多个类加载器,并且您的 sinlgeton 模式中断,因为您将拥有该类的多个实例。

在应用程序服务器(可能在集群环境中)中,单例唯一可接受的用途是单例完全无状态,并且仅用作访问全局数据/功能的便利。

我建议检查您的应用程序服务器供应商针对此问题的解决方案。大多数(如果不是所有)供应商都会为您的需求提供一些解决方案。

特别是对于您说您正在使用的 Glassfish,请查看对 Glassfish 的 Singleton EJB 支持。它可能就像添加单个注释一样简单。

于 2009-03-19T14:12:53.860 回答
3

我会说创建一个单例实际上是唯一可行的想法。假设这个“黑匣子”内的代码已知使用静态字段,那么创建这个外观的两个实例是绝对不安全的。否则结果是不可预测的。

于 2009-03-19T02:22:24.207 回答
2

这远非一个坏主意,在我看来,它实际上可能是一个相当不错的主意。

仅从程序设计的角度来看:如果您的黑匣子在概念上是一个“对象”,具有对其起作用的属性和方法,那么将其变成一个对象,即使只有其中一个实例化。

于 2009-03-18T23:35:25.810 回答
2

它应该可以工作,但是您可能需要处理一些问题。

线程,正如你所提到的。MDB 在 EJB 容器中运行,您无法在其中创建自己的线程,因此存在潜在问题。如果您可以访问实际代码(听起来像您这样做),您可能需要进行一些重构以消除线程或使用“批准的”线程方法。CommonJ TimerManager 可能会在您陈述的情况下工作,因为它会在一定时间间隔内执行某些任务。大多数应用服务器都有可用的实现(包括 WAS 和 Weblogic)。

类加载 - 这取决于您的配置。如果单例是从同一个 EAR 中的 MDB 创建和操作的,那么您会没事的。单独的 EAR 将意味着不同的类加载器和 Singleton 的多个实例。如果没有更多信息,无法评论这是否会成为您的问题。

于 2009-03-19T13:42:38.190 回答
2

我错过了一点?您提到“黑盒代码”包含状态。MDB 可能限制为每个目标 1 个实例,但如果没有适当的配置,您最终会得到一些 MDB。所有这些都与您的“黑盒代码”的单个实例一起工作。对我来说,这似乎不是一个好主意,因为一个 bean 将覆盖另一个 bean 之前创建的“黑盒代码”状态。

于 2009-03-20T20:11:55.213 回答
1

在我看来,更符合您要求的工件是 JBoss MBean。(如果您正在考虑将 JBoss 作为 AS 候选人)。

标准 MBean 示例

在 JBoss 集群的情况下,MBean 也可以部署为单例。

使用 JBoss 进行集群

我希望这对你有用。

拉法。

于 2009-03-23T13:40:57.857 回答
0

尽快修复代码以消除静态问题。单身人士并不是朝着正确方向迈出的一步——它们只是增加了额外的误导。

于 2009-03-19T15:14:26.020 回答
0

不要在状态可能改变的地方使用单例。

公开你的黑盒类的全局实例似乎不是要走的路。很多时候,单例看起来会让你的事情变得更轻松,并且在某种程度上他们可以,但它经常会反过来咬你,你最终不得不重组一大块代码。

于 2009-03-21T04:16:49.447 回答
0

在网络服务器世界中,一个对象的范围可以是请求、会话或应用程序。也许您需要的是一个应用程序范围的对象。

在文档中搜索“应用程序范围对象”或“应用程序生命周期对象”。

于 2009-03-21T05:39:46.750 回答
0

为什么不为空白框的东西创建一个休息接口并让客户端进行http调用呢?

于 2009-03-23T13:44:11.250 回答
0

IMO,拥有一个满足单例需求的 EJB 容器是个好主意。在 Java EE 6 中,在会话 bean 中放置一个 @Singleton 注释会为您提供一个命名的单例。

于 2011-08-09T21:13:50.613 回答