I can think of some complex solutions for this problem, but I need to know if theres any standard design pattern for this. The problem - I have a control class, that gets inputs continously (asynchronously) from a source. It has to buffer and maintain them. There are a few threads running at different speeds, that take the elements 1 by 1 from the control class and process them. Some thread might be faster than others, so it can come back sooner and ask for the next element in the queue. The control class gets input at a huge rate, so i cant afford to keep everything in memory. That is, as and when ALL the threads finish using an object, i have to remove it from the buffer. Also, the control class has to somehow remember the element that should be returned to a particular thread (when that thread comes back asking for the next element). The issues are that, I feel having a separate buffer for each thread might shoot the memory usage up... Also, if i just maintain the buffer in the control class alone, and build intelligence in it to take care of cleaning up itself, and also serving the threads, im not sure of the design.... Please help me with a good design, suggest any common design pattern if any... and also the apt java collection class to be used... Thanks Karthik.
Thanks<br />Karthik<br />SCJP 1.4, CCNA.<br /> <br />"Success is relative. More the success, more the relatives."
I haven't joined the design pattern gang yet, but I have a couple of suggestions which may be helpful. I presume part of your problem is in matching "next part" to the appropriate thread. You can try creating some kind of message headers and message IDs for this purpose. I think it is better to allow the thread to select the appropriate message. The Q controller is the place where the pipe narrows, so you need to keep the flow in that part as fast as possible. The Q controller should not keep a message in memory once it has been delivered to a process. A process should write object to persistent storage once it is done with a complete message. If it is possible the thread should keep the essential data from one message (part) and destroy the message object once it is done with it. Hope this helps.
Joined: Dec 22, 2002
Thanks for the reply. I have some doubts here. Do you mean to say that after i hand over an element to a thread, i remove it? then wat about the other threads that might ask for the same later? I agree that the threads should keep track of the next index of the data to get. But again, the controller should only should only give those index values(?) as it keeps deleting finished entries from buffer (hence changing the indices). Is that right?
Originally posted by Karthik Veeramani: The issues are that, I feel having a separate buffer for each thread might shoot the memory usage up...
How many objects do you expect to be in the buffer at the same time? Remember, you don't need to duplicate the actual objects, only the references to them. Without knowing more about the problem, I would certainly try that simple implementation mentioned above and profile the memory usage. If it *really* is a problem, it shouldn't be to hard to refactor to a more sophisticated solution.
The soul is dyed the color of its thoughts. Think only on those things that are in line with your principles and can bear the light of day. The content of your character is your choice. Day by day, what you do is who you become. Your integrity is your destiny - it is the light that guides your way. - Heraclitus
Joined: Apr 30, 2003
There should be two ways in which a thread can ask the Q handler for a message [*]give me the first message from the Q [*]give me the message with this message ID"
It is presumed that all parts of one message will have the same message ID. Additionally you could build in a part ID so that the thread doesn't get part 3 before part 2.. When the thread asks the Q handler for a specific message (and message part number), the Q handler will iterate through the message container until the correct message is found. If the message is not found it should exit and retry, if the required message is not found after n number of attempts you conclude that some thing has gone wrong enter into an error handling routine. All removals from the Q should be destructive or else you will eventually run out of memory. This involves some performance overhead but it will not be much. A memory leak is a much more serious thing. This is based on the assumption that a message which has been read by one thread does not need to be read by another thread. If that is not the case then there is something fundamentally wrong with the design of the message handling process. You may need to rethink your approach. What is the relationship between the two systems? If it's not a Host To Host (also known as peer to peer) relationship you can consider the sessions approach where each thread creates a session with each client. Actually some host to host messaging requirements can be re-engineered into a pseudo client-server protocol. It just needs some lateral thinking.
Kevin P.S. If the thread asks for the first message from the Q, then deliver the first message which is marked part 1. [ May 08, 2003: Message edited by: Kevin Arnold ]
Joined: Dec 22, 2002
This is based on the assumption that a message which has been read by one thread does not need to be read by another thread.
This is not the case. This problem is not like thread pooling, where any thread can do the job on any of the elements. Each thread has to work on each of the elements (objects), and send the result to their own destinations. The whole thing, Q controller, its buffer and the threads have to work as a system. 1 method in the controller will be exposed to another system, through which the other system adds objects to the buffer (asynchronously). The method im using right now is something similar to what u said. That is, exposing 1 method for the threads to call (like getNextElement(int id)). This method returns an integer for each thread, and that is the index that thread should use next time, to get its next message. I used a hashmap, with an Integer key and the object to be processed as value. I count the no. of accesses to an object in the map when any thread asks for it, see if all the threads have accessed it, then delete the element. But I find it very complicated, as there are many issues to be taken care of. For eg, the integer im using as key will reach its max at some point. Then i have to take care of resetting the indices i give to the threads. This is just 1 eg. of the problems i hav with this design.
Joined: Jul 11, 2001
Karthik, I share your concerns about the design - I also think it is rather fragile and hard to maintain. Can you please explain why you do have such strong concerns about memory consumption that you didn't try a simpler solution first? Thanks!