2

I am trying to make a class as ThreadSafe Singleton but somehow I am not able to understand how to make ThreadSafe Singleton class which can accepts parameter.

Below is the class which I am using from this github link which I am using currently to make a connection to 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;
    }
}

And this is the way I am calling the above class -

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());
}

Now what I need is if I am calling these two below methods from any class in my program, I should be able to get an instance of it. So I am thinking to make above class as a Thread Safe Singleton so that I can access these two methods across all my java program.

isLeader()
getClient()

How do I make above class as ThreadSafe singleton and then make use of isLeader() and getClient() across all my classes to see who is the leader and get the client instance..

I need to do this only at the initialization time and once it is done, I should be able to use isLeader() and getClient() across all my classes.. Is this possible to do?

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

This is more of Java question not Zookeeper stuff..

AKIWEB
  • 19,008
  • 67
  • 180
  • 294
  • Is there anything you need besides the patterns listed at http://stackoverflow.com/q/7048198/2636001 ? – dst Feb 13 '14 at 23:04

1 Answers1

3

A singleton which requires a parameter is a bit of a contradiction in terms. After all, you'd need to supply the parameter value on every call, and then consider what would happen if the value was different to an earlier one.

I would encourage you to avoid using the singleton pattern at all here. Instead, make your class a perfectly normal one - but use dependency injection to provide a reference to a single configured instance to all your classes that need it.

That way:

  • The singleton nature isn't enforced, it's just a natural part of you only needing one reference. If later on you needed two references (e.g. for different Zookeeper instances for some reason) you can just configure the dependency injection differently
  • The lack of global state generally makes things much easier to test. One test might use one configuration; another test might use a different one. No singleton, no problem. Just pass the relevant reference into the constructor of the class under test.
Jon Skeet
  • 1,421,763
  • 867
  • 9,128
  • 9,194
  • Thanks Jon. I might supply parameter only at initialization time, and after that I don't want to specify any parameter and just want to use `isLeader()` and `getClient()` method in all the classes. – AKIWEB Feb 13 '14 at 23:46
  • In that scenario, I should also use DI to pass around? – AKIWEB Feb 13 '14 at 23:57
  • @AKIWEB: Yes, that's what I'd do. You *could* make two static methods, one to initialize the singleton and one to fetch it, but I really wouldn't. – Jon Skeet Feb 14 '14 at 06:30