2

Similar to Singleton class I want to create a Fiveton class which can create maximum 5 instances of the class. Different threads are trying to access instances of this class (hence getInstance method needs to be provided). However class is heavy so the instances must not be eagerly created i.e. created on demand.

Also contract is that threads are allotted instances in round robin fashion i.e. Thread no.1, 6, 11 get instance 1 of Fiveton object. If the instance is being used by a thread, they wait for the lock (it may be possible that thread 6 and 11 wait for instance 1 and thread 11 may get it but in no circumstance thread 11 should get instance 2). Similarly, Thread no. 2, 7, 12 should get instance 2.

halfer
  • 19,824
  • 17
  • 99
  • 186
  • 2
    What are your thoughts on how to achieve this? – assylias Apr 10 '13 at 07:45
  • You can use the new java.concurrent classes for locks on each object. Plus each thread needs a id notion and which object it should get based on id. Can use a util class that takes your Runnable that is running on one of the 5 threads, looks at its id, asks lock and waits for correct object that is in a static list. – tgkprog Apr 10 '13 at 08:45
  • i also want ontract is that threads are allotted instances in round robin fashion i.e. Thread no.1, 6, 11 get instance 1 of Fiveton object. If the instance is being used by a thread, they wait for the lock (it may be possible that thread 6 and 11 wait for instance 1 and thread 11 may get it but in no circumstance thread 11 should get instance 2). Similarly, Thread no. 2, 7, 12 should get instance 2. –  Apr 10 '13 at 10:52

3 Answers3

3

Don't code that in your class itself*, instead, use an object pool.

A good library to get you started is Apache Commons / Pool

Another one I don't know but that claims to be faster is furious-objectpool

Use one of the supplied implementations or use the libraries as a basis to build your own custom pool.

* Why not code that into the class itself? Because what a class does and how to get access to instances of a class are unrelated concerns. The class should concentrate on it's core purposes and not about managing itself.

Sean Patrick Floyd
  • 292,901
  • 67
  • 465
  • 588
  • But this wont take care of thread 1, 6, 11 getting object 1. Unless you have 5 pools with 1 object and the specific code in the threads asking the correct pool for the object. Pools do not block in definately too. Need a lock and wait logic for this – tgkprog Apr 10 '13 at 08:44
  • I don't think a typical object pool will satisfy the cyclicality requirement. – assylias Apr 10 '13 at 08:44
  • That's why I wrote "Use one of the supplied implementations or use the libraries as a basis to build your own custom pool" – Sean Patrick Floyd Apr 10 '13 at 08:46
  • well i don't think a pool be optimal. need to be handled separately and generically . but via a object array in an SingleObjectServer and individual locks. – tgkprog Apr 10 '13 at 09:14
  • can anyone give me custom code for this . –  Apr 10 '13 at 09:26
  • i need java code for the above problem,have to do in my project . –  Apr 10 '13 at 09:27
  • the given archive will not do Thread no.1, 6, 11 get instance 1 of Fiveton object. If the instance is being used by a thread, they wait for the lock (it may be possible that thread 6 and 11 wait for instance 1 and thread 11 may get it but in no circumstance thread 11 should get instance 2). Similarly, Thread no. 2, 7, 12 should get instance 2. –  Apr 10 '13 at 09:34
  • supprse thread 1 came into syncronise block ,one object created and added into list.same for 2,3,4 ..1) what for fifth thread .... and how these thead will use the object and when 1 is using how 6 will wait –  Apr 10 '13 at 10:48
  • for the fifth thread the same thing happens as for 1,2,3,4 : "one object created and added into list" because you wanted to use 5 instances (0-4) so thread 5 has instance no. 0 – Stephan Apr 10 '13 at 12:00
  • +1 for "what a class does and how to get access to instances of a class are unrelated concerns." – Tansir1 Apr 10 '13 at 12:35
1

If you care about contention while instances are created (i.e. you don't want Thread 6 to block because Thread 2 is still creating its instance), you can use a lock striping strategy - in this implementation, it is assumed that Thread 1, 2, ... call getInstance one after the other:

class CyclicFiveton {

    private static final CyclicFiveton[] fivetons = new CyclicFiveton[5];
    private static final Object[] locks = new Object[5];
    private static final AtomicInteger counter = new AtomicInteger();

    static {
        for (int i = 0; i < 5; i++) {
            locks[i] = new Object();
        }
    }

    private CyclicFiveton() {
    }

    public static CyclicFiveton getInstance() {
        int index = counter.getAndIncrement() % 5;
        synchronized (locks[index]) {
            CyclicFiveton fiveton = fivetons[index];
            if (fiveton == null) {
                fiveton = new CyclicFiveton();
                fivetons[index] = fiveton;
            }
            return fiveton;
        }
    }
}
assylias
  • 321,522
  • 82
  • 660
  • 783
  • why did you used synchronized (locks[index])? instead you could use synchronized (fivetons[index]) right? – Stephan Apr 10 '13 at 14:27
  • 1
    @Stephan It is usually better practice to synchronize on a field that is not accessible/synchronizable by a client to the API. In this situation synchronizing on `fivetons[index]` synchronizes on the same instance that is returned. You can read more here http://stackoverflow.com/questions/442564/avoid-synchronizedthis-in-java – John Vint Apr 10 '13 at 14:37
  • @assylias +1, but wouldn't it make sense to use a `ConcurrentHashMap` and use the built in synchronization? – John Vint Apr 10 '13 at 14:39
  • 1
    @JohnVint +1 yeah ur right, plus the fact that using synchronized on `fivetons[index]` you will not be able to do the lazy initialization – Stephan Apr 10 '13 at 14:47
  • @Stephan `fivetons[index]` could be null. – assylias Apr 10 '13 at 15:52
  • @JohnVint Not sure you can achieve "full laziness" (putIfAbsent will need to pre-create the object and you might end up creating it twice). – assylias Apr 10 '13 at 16:00
  • @assylias You're right - missed his need to make it lazy – John Vint Apr 10 '13 at 16:02
0

If i understood you requirements correctly you can try something like this:

public class Fiveton {

private Fiveton(){
    //create private constructor to prevent new instances from outside of the class
}

private static final int MAX_NB_INSTANCES = 5;
private static List<Fiveton> instances; 

/**
 * Should be called once at the beginning 
 */
public static void init(){
    instances =  new ArrayList<Fiveton>(MAX_NB_INSTANCES);
    for(int i=0;i<MAX_NB_INSTANCES;i++){
        instances.add(new Fiveton());
    }
}

/**
 *  threadNb can be the name of the Thread::getName() 
 * 
 * @param threadNb
 * @return Fiveton
 */
public static Fiveton getInstance(int threadNb){
    synchronized(instances.get(threadNb%MAX_NB_INSTANCES)){
        return instances.get(threadNb%MAX_NB_INSTANCES);
    }       
}  

/**
 * other logic
 * 
 */

}

All you need is to add the logic behind the Fiveton object.

UPDATE

Or as Sean Patrick Floyd well pointed out you can use this just to manage the instances and have a different class (object) for the logic that you want its much cleaner and transparent this way.

UPDATE

Added lazy initialization

Stephan
  • 8,000
  • 3
  • 36
  • 42
  • The op wants lazy initialization. – assylias Apr 10 '13 at 08:43
  • @assylias : thx, i missed that ... anyway its easy to implement the lazy initialization : 1. remove init method 2. in get instance method you check if the instance you want (threadNb%MAX_NB_INSTANCES) exists and if not create it – Stephan Apr 10 '13 at 08:52
  • what about thread access;Thread no.1, 6, 11 get instance 1 of Fiveton object. If the instance is being used by a thread, they wait for the lock (it may be possible that thread 6 and 11 wait for instance 1 and thread 11 may get it but in no circumstance thread 11 should get instance 2). Similarly, Thread no. 2, 7, 12 should get instance 2. –  Apr 10 '13 at 09:35
  • this is achieved by threadNb%MAX_NB_INSTANCES : thread no.1 -> 1%5=1 it gets instance 1 , thread no.6 -> 6%5=1 it gets instance 1 etc so there is no way for thread no. 11 to get instance 2. Clear now? or you had another problem? – Stephan Apr 10 '13 at 09:59
  • thanks, but one question on this .. what if thread 1 using instance one .. then thread 6 and 11 have to wait .. where is logic for that ...i mean " If the instance is being used by a thread, they wait for the lock (it may be possible that thread 6 and 11 wait for instance 1" what about this logic –  Apr 10 '13 at 10:36
  • for first question : since the method is synchronized thread 6 and 11 will wait till thread 1 gets the instance . Isn't that what you what? – Stephan Apr 10 '13 at 11:35
  • for second question 5%5=0 so it will receive instance no. 0 . you have 5 instances from 0 to 4 – Stephan Apr 10 '13 at 11:35
  • if method is syncronise ... then when thread 1 geting instance,other all will wait ..after 1 if 2 get into the method and instance one is not accessing by thread 1,then also 6 and other have to wait .... as method if syncronise –  Apr 10 '13 at 11:58
  • second as per problem :If the instance is being used by a thread, they wait for the lock (it may be possible that thread 6 and 11 wait for instance 1 ) .. means 6 and 11 only have to wait for one .not others ... but as per the suggested implementation method is only access by one method at a time... so when thread 2 is using it that time also 6 and 11 waiting –  Apr 10 '13 at 11:59
  • what about round robin ... –  Apr 10 '13 at 12:27
  • i got ur point so i've updated the logic and now you have synchronized only on the instance you need so for example thread 2 will not wait for thread 1 . is it ok for you? – Stephan Apr 10 '13 at 12:27
  • well it implements round robin principle : you have even distribution and also circular order 1->1,2->2,3->3,4->4,5->0,6->1 etc – Stephan Apr 10 '13 at 12:30
  • i am sorry but still bit confusion . as per need it says thread 1 uses till than 6 wait . but in this given code where we having multiple thread and using instance ..it just creating –  Apr 10 '13 at 12:47
  • what do you mean by using instance ? i assumed you just needed to return that instance – Stephan Apr 10 '13 at 12:55
  • i mean the code who use the above code.... a kind of testing –  Apr 10 '13 at 13:15
  • and how the above code is round robin –  Apr 10 '13 at 13:22
  • i assumed you mean this : http://en.wikipedia.org/wiki/Round-robin_scheduling . "As the term is generally used, time slices are assigned to each process in equal portions and in circular order, handling all processes without priority" since every thread i assume will have the same things to do the you can say "time slices are assigned to each process in equal portions" , here we have circular order due to %5 and all threads have the same prio (FIFO) – Stephan Apr 10 '13 at 13:32
  • ok thanks .. so by default it will be round robin –  Apr 11 '13 at 06:27
  • @user2247776 : yes and the same principle is applied also int the solution proposed by `assylias` only that he has a better synchronization system so i recommend to use his solution – Stephan Apr 11 '13 at 06:43
  • but again ... its not lazy loading –  Apr 11 '13 at 06:46
  • thanks for giving the solution but I also want each thread's run method and it should go on sleep after taking lock on object and then other corrosponding thread must wait (if 1's run method took lock n went sleep ,6 11 should in waiting mode) –  Apr 15 '13 at 05:09
  • if you acquire the lock with a thread and another thread wants to acquire the same lock the by default it will wait until the lock is released . if you want to put the thread to sleep after it acquired the lock (even though i do not see the purpose for this) you could use the solution provided by @assylias – Stephan Apr 15 '13 at 07:04