Java 如何使线程安全的单例类可以接受参数?

Java 如何使线程安全的单例类可以接受参数?,java,thread-safety,singleton,apache-zookeeper,apache-curator,Java,Thread Safety,Singleton,Apache Zookeeper,Apache Curator,我试图创建一个名为ThreadSafe Singleton的类,但不知何故,我无法理解如何创建可以接受参数的ThreadSafe Singleton类 下面是我从这个github使用的类,我当前使用它来连接Zookeeper- public class LeaderLatchExample { private CuratorFramework client; private String latchPath; private String id; private

我试图创建一个名为
ThreadSafe Singleton
的类,但不知何故,我无法理解如何创建可以接受参数的
ThreadSafe Singleton

下面是我从这个github使用的类,我当前使用它来连接Zookeeper-

public class LeaderLatchExample {

    private CuratorFramework client;
    private String latchPath;
    private String id;
    private LeaderLatch leaderLatch;

    public LeaderLatchExample(String connString, String latchPath, String id) {
        client = CuratorFrameworkFactory.newClient(connString, new ExponentialBackoffRetry(1000, Integer.MAX_VALUE));
        this.id = id;
        this.latchPath = latchPath;
    }

    public void start() throws Exception {
        client.start();
        client.getZookeeperClient().blockUntilConnectedOrTimedOut();
        leaderLatch = new LeaderLatch(client, latchPath, id);
        leaderLatch.start();
    }

    public boolean isLeader() {
        return leaderLatch.hasLeadership();
    }

    public Participant currentLeader() throws Exception {
        return leaderLatch.getLeader();
    }

    public void close() throws IOException {
        leaderLatch.close();
        client.close();
    }

    public CuratorFramework getClient() {
        return client;
    }

    public String getLatchPath() {
        return latchPath;
    }

    public String getId() {
        return id;
    }

    public LeaderLatch getLeaderLatch() {
        return leaderLatch;
    }
}
这就是我给上述班级的称呼-

public static void main(String[] args) throws Exception {
        String latchPath = "/latch";
        String connStr = "10.12.136.235:2181";
        LeaderLatchExample node1 = new LeaderLatchExample(connStr, latchPath, "node-1"); // this I will be doing only one time at just the initialization time
        node1.start();

        System.out.println("now node-1 think the leader is " + node1.currentLeader());
}
现在我需要的是,如果我从程序中的任何类调用下面两个方法,我应该能够得到它的一个实例。所以我想把上面的类作为线程安全的单例,这样我就可以在我所有的java程序中访问这两个方法

isLeader()
getClient()
如何使上述类成为线程安全的单例,然后在所有类中使用
isLeader()
getClient()
,以确定谁是领导者并获取客户端实例

我只需要在初始化时执行此操作,一旦完成,我应该能够在所有类中使用
isLeader()
getClient()
。。这可能吗

// this line I will be doing only one time at just the initialization time
LeaderLatchExample node1 = new LeaderLatchExample(connStr, latchPath, "node-1");
node1.start();

这更多的是Java问题,而不是Zookeeper的东西。

一个需要参数的单例在术语上有点矛盾。毕竟,您需要在每个调用上提供参数值,然后考虑如果值与较早的值不同,将会发生什么。 我鼓励您在这里避免使用单例模式。相反,让您的类成为一个完全正常的类——但是使用依赖项注入为所有需要它的类提供对单个配置实例的引用

这样:

  • 单身的本质不是强制的,它只是你自然的一部分,只需要一个参考。如果以后需要两个引用(例如,出于某种原因,针对不同的Zookeeper实例),您可以以不同的方式配置依赖项注入
  • 缺乏全局状态通常使事情更容易测试。一个测试可能使用一个配置;另一个测试可能使用不同的测试。没有单身汉,没问题。只需将相关引用传递到被测试类的构造函数中

除了上面列出的图案之外,您还需要什么吗?谢谢Jon。我可能只在初始化时提供参数,之后我不想指定任何参数,只想在所有类中使用
isLeader()
getClient()
方法。在这种情况下,我还应该使用DI来传递?@AKIWEB:是的,我会这样做。您可以创建两个静态方法,一个用于初始化singleton,另一个用于获取它,但我确实不这么做。