4

I want to write a java class that can be instantiated only 5 times just like you have singleton class which have only one instance.

Apart from this the instances should be picked in round robin basis.

Suppose I have a class A. I should be only able to create 5 instances of this class. Say I have InstanceA_1, InstanceA_2, InstanceA_3, InstanceA_4, InstanceA_5. Whenever I need to use them they should be picked on round robin basis.

Kamal
  • 3,878
  • 4
  • 21
  • 24

11 Answers11

15

Just as enum is recommended by Effective Java 2nd Edition to implement singleton, this solution also uses enum to implement... quadrupleton?

import java.util.*;

public enum RoundRobin {
    EENIE, MEENIE, MINY, MO;

    private final static List<RoundRobin> values =
        Collections.unmodifiableList(Arrays.asList(values()));
    // cache it instead of creating new array every time with values()

    private final static int N = values.size();
    private static int counter = -1;

    public static RoundRobin nextInstance() {
        counter = (counter + 1) % N; // % is the remainder operator
        return values.get(counter);
    }

    public static void main(String[] args) {
        for (int i = 0; i < 10; i++) {
            System.out.println(RoundRobin.nextInstance());
        }
        // EENIE, MEENIE, MINY, MO, EENIE, MEENIE, MINY, MO, ...
    }
}

Extending this to quintupleton is self-explanatory.

See also

  • Effective Java 2nd Edition, Enforce singleton property with a private constructor or an enum type

    As of release 1.5., there is a third approach to implementing singletons. Simply make an enum type with one element. This approach is functionally equivalent to the public field approach, except that it is more concise, provides serialization mechanism for free, and provides an ironclad guarantee against multiple instantiation, even in the face of sophisticated serialization or reflection attacks. While this approach has yet to be widely adopted, a single-element enum type is the best way to implement a singleton.

Related questions

Community
  • 1
  • 1
polygenelubricants
  • 376,812
  • 128
  • 561
  • 623
  • @mchr: You presume wrong. Enum is ironclad guaranteed by the language itself to have tightly controlled instantiation, allowing you to use `==` instead of `equals` should you choose to do so. – polygenelubricants Aug 03 '10 at 19:30
  • 2
    Sorry I should have been much clearer about which part I considered threadsafe :). public static RoundRobin nextInstance() This method is doing unsynchronized access to an int. Surely multiple threads could end up selecting the same instance. – mchr Aug 04 '10 at 11:23
  • @mchr: Ah yes, the `nextInstance` could be made `synchronized` and `counter` be `volatile`, or perhaps an atomic modular `counter` could be used, etc. Good point. – polygenelubricants Aug 04 '10 at 11:35
2

You need something like an Object pool. The simplest implementation would be to have a singleton containing a List of 5 objects, and whenever you call getInstance(..), the list should be iterated and one of the objects returned.

Bozho
  • 588,226
  • 146
  • 1,060
  • 1,140
  • My initial reaction was to suggest an object pool, but Kamal didn't mention the need to checkout/checkin the five instances of class A, or whether the checkout methods should block until a pooled A instance is available. – Phil M Aug 03 '10 at 19:43
1

Is this a homework?

Why don't you create a Factory that creates 5 instances and store them in a list? When someone calls Factory.getInstance(), it will then get the right instance using the right index of the list.

limc
  • 39,366
  • 20
  • 100
  • 145
1

Would a pool work (e.g. Apache Commons Pool)?

Kevin Hakanson
  • 41,386
  • 23
  • 126
  • 155
1

Well, something along these lines:

  • Make the constructor private
  • Create the five instances in a static initializer, and store the references in an array
  • Keep an index to indicate the next one to return
  • Write a static method to return the next value and increment the index.

To be thread-safe you will need to lock within the static method. You could use AtomicInteger, but wrapping is tricky. You could always use AtomicInteger or AtomicLong, increment each time, and index using the % operator... but when the index wrapped, you'd get a discontinuity. That may or may not be a problem for you.

(This is assuming you don't mind creating all five instances up-front. That certainly makes things easier.)

Jon Skeet
  • 1,421,763
  • 867
  • 9,128
  • 9,194
1

I imagine that all you would need to do is extend the Singleton pattern to use a counter. Something like...

// Declare a list holding the 5 Objects
List<Foo> instances = new ArrayList<Foo>(5);
// Keep track of which Object you are returning next
int curr = 0;

...

static Foo getInstance() {
    // Only instantiate when necessary
    if (instances.get(curr) == null) {
        instances.set(curr, new Foo());
    }
    Foo toReturn = instances.get(curr);
    // Use modulus to loop back to 0 after 4
    curr = (curr + 1) % 5;
    return toReturn;
}

Disclaimer: I'm assuming you don't need the code to be thread-safe.

Justin Ardini
  • 9,768
  • 2
  • 39
  • 46
1

you have to create static instance variable to keep track all your objects.Then you may use an if statement on the constructor to throw an exception or to exit from the system whenever the user initialize the class 5 times.

public class JustFive {
    public static int count;
    
    public JustFive(){
        if(count>=5){
            System.out.println("you can not create another instance");
            System.exit(1);
        }
        else count++;
        System.out.println(count);

    }}

Youmight want to use static factory mathod. I am showing you the not recommended unusual way.

yome fisseha
  • 81
  • 1
  • 5
  • 1
    While this code may/may no solve the question, [including an explanation](https://meta.stackexchange.com/questions/114762/explaining-entirely-code-based-answers) of how and why this solves the problem would really help to improve the quality of your post, and probably result in more up-votes. Remember that you are answering the question for readers in the future, not just the person asking now. Please edit your answer to add explanations. – Drew Aug 16 '19 at 06:22
0

Create five static instances. Keep an index of the last instance. Make a private constructor. Use a method to get an instance (similar to a singleton);

public class MyObject {

private static final MyObject instance_1 = new MyObject();
private static final MyObject instance_2 = new MyObject();
private static final MyObject instance_3 = new MyObject();
private static final MyObject instance_4 = new MyObject();
private static final MyObject instance_5 = new MyObject();

private static final MyObject[] instances = new MyObject[]{instance_1, instance_2,instance_3, instance_4,instance_5};

private MyObject() {

}

private static volatile int index = 0; //in a multi-threaded evironment, you should use volatile

    /**
     * The following code is not thread safe
     */
public static MyObject getInstance() {
    MyObject instance = instances[index];

            if (index == 4) {
                index = 0;
            } else {
                index++;
            }
    return instance;
}

}

Thierry Roy
  • 8,452
  • 10
  • 60
  • 84
  • Pssh: you forgot to reset the index to zero when last element is returned :) – BalusC Aug 03 '10 at 17:54
  • 2
    Why would you bother keeping the five separate variables? Why not just initialize the array in a loop? – Jon Skeet Aug 03 '10 at 17:55
  • 2
    ...or during array initialization itself :) E.g. `new MyObject[] { new MyObject(), ... }`. – BalusC Aug 03 '10 at 17:57
  • @Jon: I think it's more readable that way. It should be clear that there is only 5 instances. But if there were more instance (>20), I would use for loop). :) – Thierry Roy Aug 03 '10 at 17:58
  • 2
    @THierry-Dimitry: Whereas I get suspicious when there's a variable which isn't used after initialization... – Jon Skeet Aug 03 '10 at 18:02
  • @Thierry-Dimitri: If you want to keep that format, a static initializer is better in this case: `static { instances[0] = new MyObject(); /*...*/ }` It's never a good idea to use static final fields as temporary variables. – Mark Peters Aug 03 '10 at 18:07
0

Here is a very simplistic solution. Note that this isn't thread safe:

class ClassA {

    private final List<ClassA> instances = Arrays.asList(new ClassA(), new ClassA(), new ClassA(), new ClassA(), new ClassA());

    private ClassA() {}

    public static ClassA getInstance() {
        Collections.shuffle(instances);
        return instances.get(0);
    }

}
Jordan S. Jones
  • 13,703
  • 5
  • 44
  • 49
0
 class OnlyFiveTime {

    private static LinkedList<OnlyFiveTime> instaces = new LinkedList<OnlyFiveTime>();
    private static final int count = 5;

    public static OnlyFiveTime getInstace() {


        if(instaces.size() != count) {
            instaces.addLast(new OnlyFiveTime());
        }

        OnlyFiveTime robinRound = instaces.removeFirst();

        instaces.addLast(robinRound);

        return robinRound;

    }

    private OnlyFiveTime() {

    }

}
0

A simplified RoundRobin.

import java.util.*; 

public enum RoundRobin { 
    EENIE, MEENIE, MINY, MO; 

    private final static RoundRobin[] values = values(); 
    private static int counter = -1; 

    public static RoundRobin nextInstance() {
        counter = (counter + 1) % values.length;
        return values[counter]; 
    } 

    public static void main(String[] args) { 
        for (int i = 0; i < 10; i++) 
            System.out.println(RoundRobin.nextInstance()); 
        // EENIE, MEENIE, MINY, MO, EENIE, MEENIE, MINY, MO, ... 
    } 
} 
Peter Lawrey
  • 525,659
  • 79
  • 751
  • 1,130