Take the 2-minute tour ×
Programmers Stack Exchange is a question and answer site for professional programmers interested in conceptual questions about software development. It's 100% free, no registration required.

I'm making a project with 5 packages. The packages can communicate with each other by sending Messages to a central MessageQueue in the Main package and that MessageQueue takes care of all the messages. (cfr.: http://en.wikipedia.org/wiki/Java_Message_Service)

Provided this image:

Diagram

the packages would be the clients (both publisher and subscriber) and the MessageQueue would be the topic.

I'm now implementing the MessageQueue (a.k.a. the Topic in the image above) and packages can already subscribe to Messages and packages can also publish a Message.
Publishing a Message is just adding the Message to a queue 'inside' the MessageQueue.

So at a given time during execution there can be 0, 1 or more messages in the MessageQueue and now i must make sure the MessageQueue processes all these messages correctly (and in order).

A way of doing this could look like this:

public class MessageQueue {

    public MessageQueue(){
        //initialising etc.
        processMessages();
    }

    private void processMessages(){
        while(/*program is running*/){
            if(queue.isNotEmpty()){
                /*process first message in queue*/
            }
        }
   }

However, i believe this is not a great design and is sometimes referred to as busy waiting?
How could i approach this in a better way (without using any standard APIs ofcourse)?

I would also like to apologise that the image isn't embedded, but i need 10 reputation before i can do that. If someone with more reputation could edit my post so that the image is embedded, i would greatly appreciate that.

share|improve this question
    
You should have gone to SO. –  Jas Apr 22 '11 at 17:14
    
Well, i'm not 100% sure about that since i'm not looking for raw code but more concepts/design patterns/... Those things are mentioned in the FAQ of "Programmers". (*crosses fingers i didn't read that wrong*) –  Aerus Apr 22 '11 at 17:45
add comment

2 Answers

up vote 2 down vote accepted

As you said, you are doing a busy waiting, here. You need to make your thread block until the message queue becomes non-empty.

The primitives for doing that are the methods wait and notify of class Object. Using correctly these primitives can be tricky, even when you have a good understanding of multithreading. Basically, wait makes a thread block, and notify sends a signal to the waiting thread.

A more high-level tool (which are certainly built on top of wait and notify) are the classes from the package java.util.concurrent.locks. Mainly, Lock and Condition. A Condition have similar methods than wait and notify.

Another tool you can use is a BlockingQueue. When asked to give an object, a blocking queue will block the current thread until it becomes non-empty. Under the hood, it uses the same wait/notify primitives described above. It's a valid solution for your specific problem.

A higher level solution, which abstracts you from the executing thread, is to use an ExecutorService. ExecutorService.newSingleThreadExecutor() would do the trick. Just submit Runnable objects to an ExecutorService, and it will run them asynchronously in a dedicated thread.

You can choose any of these solutions to implement your messaging system. It only depends on how much control you want, or what level you are trying to master (if you do this to learn programming).

share|improve this answer
    
Thanks, this gives me everything to start implementing this in a more efficient way ! –  Aerus Apr 22 '11 at 17:42
add comment

Your question is really unclear. Why are you trying to implement your own middleware instead of using a free off-the-shelf JMS implementation like ActiveMQ? It's extremely hard to implement something as robust as widely available frameworks.

Most implementations give you both synchronous (Blocking) messages or Asynchronous ones (with callbacks). Thus alleviating the need to busy wait.

If you're wondering what happens under the hood - most of the JMS implementations are multithreaded. So there's a thread (run by the framework) that gets the messages, and there's the user thread that waits for the message. In a blocking message reading situation, your user thread calls the "retrieve message" operation, and if one isn't there, it blocks by waiting on a monitor. When a message arrives, the framework message handling thread "notifies" the monitor, which then wakes up the user thread to retrieve the message. Java's threading infrastructure is built exactly for this, to avoid user-visible busy waiting.

It's a good exercise to implement these yourself (often called producer-consumer), but the robustness is often PITA, so again, existing frameworks are your best bet.

BTW: I've often used JMS between packages on the same machine and often the same JVM. It's pretty efficient and makes it easy to scale. I'm willing to bet that under the hood the framework figures out that it's running on the same JVM and uses some in-memory shared space. When you move to machines on different computers, your user code doesn't change, just your latency.

share|improve this answer
add comment

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.