Still playing with multi-threading and Prod-Con, at this point I've been at this for days. Would love some help debugging; thanks in advance.

http://pastebin.com/jhHB9kTY - Main
http://pastebin.com/BZSspf3x - Consumer
http://pastebin.com/ndzAADJz - Producer
http://pastebin.com/p7YdzH1D - Product
http://pastebin.com/rxs3WzDT - Message
http://pastebin.com/JR5ywgz1 - Utiliy

2 Producers, 4 Consumers

Essentially Producers push a message onto the queue, message consists of a prod obj, date obj, and region string.
This sharedQueue[0] is checked by each Consumer for thier region in which case they store it in a local variable and append it to internal lists.

Again thanks for the help.

Recommended Answers

All 6 Replies

Can you make a small, simple, single program file that shows the problem you are working on? Or merge the six files into one file and post that.

The two important classes; iirc the error is about IllegalMonitorException; the Producers pop onto the queue , the Consumers don't pull anything.

public class Producer implements Runnable {

    protected final static List<Message> sharedQueue = new ArrayList<>();
    protected final int MAX_SIZE = 10;

    @Override
    public void run() {
        while (true) {
            synchronized (sharedQueue) {
                while (sharedQueue.size() == MAX_SIZE) {
                    try {
                        sharedQueue.wait();
                    } catch (InterruptedException e) {
                    }
                }
                sharedQueue.add(new Message(Utility.getRandomProduct(), new Date(), Utility.regionLookup(Utility.getState())));
                System.out.println(Thread.currentThread().getName() + " adding. Queue size: " + sharedQueue.size());
            }
        }
    }

    public static Message messageConsume(String region) {
        synchronized(sharedQueue) {
        while (sharedQueue.isEmpty()) {
            try {
                sharedQueue.wait();
            } catch (InterruptedException e) {
            }
        }
        if (sharedQueue.get(0).getRegion().equalsIgnoreCase(region)) {
            Message tempMessage = sharedQueue.get(0);
            sharedQueue.remove(0);
            return tempMessage;
        } else {
            return null;
        }
        }
    }
}

public class Consumer implements Runnable {

    private List<Message> consumerList = new ArrayList<>();

    @Override
    public void run() {
        while (true) {
            try {
                Message tempMessage = Producer.messageConsume(Thread.currentThread().getName());
                if (tempMessage.getRegion().equalsIgnoreCase(Thread.currentThread().getName())) {
                    consumerList.add(tempMessage);
                }  Thread.sleep(500);
            } catch (InterruptedException ex) {
                Logger.getLogger(Consumer.class.getName()).log(Level.SEVERE, null, ex);
            }
        }
    }
}

How do you test the posted code? I don't see a main() method?

Can you post the full text of the error message? I can not find: IllegalMonitorException

In Producer class inside messageConsume() method, did a call from consumer go through the loop down to the checking for region? If so, did it actually get through inside the checking region if-condition? Try to print out each line of your process to pin point where exactly is wrong.

Anyway, I see you use wait() method, but who is going to wake the thread up after the wait()? Where are you putting your notify()? A thread can't simply wake up after being wait(). The same goes to pushing message onto the queue. Once the queue is full, who is going to wake the thread up to keep pushing again?

public static Message messageConsume(String region) {
  synchronized(sharedQueue) {
    while (sharedQueue.isEmpty()) {
      try {
        sharedQueue.wait();  // Who is going to notify this thread???
      } catch (InterruptedException e) { }
    }
    System.out.println("Queue size: "+sharedQueue.size());
    if (sharedQueue.get(0).getRegion().equalsIgnoreCase(region)) {
      Message tempMessage = sharedQueue.remove(0);
      System.out.println("Removed: "+tmpMessage);
      //sharedQueue.remove(0);   // use remove() right away, don't need this
      System.out.println("Queue size after removed: "+sharedQueue.size());
      return tempMessage;
    } else {
      return null;
    }
  }
}

Personally, I would keep the synchronized block as small as I could. Also, I would keep an infinite loop out of the block (the current while loop). I would instead check if an item is returned after each loop; otherwise, I will wait.

Main consists of just instantiating and starting the threads nothing else atm.

Taywin, thanks I made a few changes and I'm no longer getting the IllegalMonitor Exception for the time being; instead a NUllPointer which I believe happens in the messageConsume; I'll check it out and post back. Thanks,

Smooth as butter, thanks!

Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.