views:

186

answers:

11

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.

+1  A: 

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
+1  A: 

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

Kevin Hakanson
A: 

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-Dimitri Roy
Pssh: you forgot to reset the index to zero when last element is returned :)
BalusC
Why would you bother keeping the five separate variables? Why not just initialize the array in a loop?
Jon Skeet
...or during array initialization itself :) E.g. `new MyObject[] { new MyObject(), ... }`.
BalusC
@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-Dimitri Roy
@THierry-Dimitry: Whereas I get suspicious when there's a variable which isn't used after initialization...
Jon Skeet
@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
+1  A: 

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
A: 

Duplicate

Sinuhe
+1  A: 

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
What would happen when `Integer.MAX_VALUE` is reached? Will the modulus approach still calculate it right?
BalusC
`curr` would never get larger than 4. :)
Justin Ardini
+2  A: 

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
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
A: 

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
Shuffle isn't fullworthy [round robin](http://en.wikipedia.org/wiki/Round-robin).
BalusC
@BalusC True, however wouldn't it achieve the desired results?
Jordan S. Jones
Shuffle: possibly return 3, 5, 1, 1, 1, 2, 5, 1, 1, 4, etc.Round robin: return 1, 2, 3, 4, 5, 1, 2, 3, 4, 5, etc.
BalusC
@BalusC - Thank you for the clarification.
Jordan S. Jones
+8  A: 
polygenelubricants
Presumably this pattern is not threadsafe?
mchr
@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
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
@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
A: 
 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() {

    }

}
Vash
A: 

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