如何为多个jvm支持创建单例java类?

时间:2012-08-20 06:05:22

标签: java

例如,我有DBManager.java Singleton Class,我必须在集群环境中部署它。 它是一个基于Web的应用程序,具有以下部署策略

Apache负载均衡器 - > Tomcat 6(群集中有3个服务器)。

我必须为3个tomcat实例维护DBManager的单个实例。

我的代码是

package com.db.util;
public class DBManager {
    private static DBManager singleInstance;
    private DBManager () {}
    public static DBManager getSingleInstance() {
        if (singleInstance == null) {
            synchronized (DBManager.class) {
                if (singleInstance == null) {
                    singleInstance = new DBManager ();
                }
            }
        }
        return singleInstance;
    }
}

我一直在寻找这个问题的解决方案,并找到了像JGroups API这样的东西。 这可以使用JGroups实现吗?任何想法,如何实现?

2 个答案:

答案 0 :(得分:6)

Java在每个实例中为您提供单例,您需要在实例之间进行某种协调,因此在任何给定时间,其中一个是活动的,但如果活动的一个死亡,则另一个实例变为活动状态。

一些应用服务器具有内置功能来控制这种协调的工作者实例,我不知道Tomcat是否具有这样的功能。

自己构建这样的功能非常困难,请参阅this question并注意到该问题提供了一个有用库的链接 - 对我来说这看起来很复杂。

但是在您的情况下,您有一个数据库,这为您提供了一个协调点。我没有详细设计这个,但我认为可以使用控制表中的专用行创建预订方案。有效地执行此操作有点棘手,平衡实例死亡的检测速度与轮询数据库的开销以查看哪个实例处于活动状态,但似乎可行。

这个想法是记录包含“reservedUntil”时间戳和“processId”。每个进程读取记录,如果它包含它自己的id并且时间戳尚未到期,则它知道它可以工作。当时间接近到期时,活动进程使用乐观锁定样式“Update where timestamp == old timestamp”来更新时间戳以管理竞争条件。每个非活动进程等待,直到它上次读取的时间戳已过期,然后尝试通过更新记录来获取控制权,再次使用乐观锁定Update where。通常,获取控制权的尝试将失败,但如果成功,我们现在有一个新的活动实例,并且由于乐观锁定,我们只能获得一个活动实例。

答案 1 :(得分:0)

Singleton仅确保给定JVM中的一个类实例。

在您的情况下,多个DBManagers的问题是什么,每个JVM一个?