0

Background:

I have an application of miniature robots (these extend Thread class) that make deals with one another at nodes of a map. I am trying to program the logic that goes into the node. The node is responsible for carrying out the deals between two bots that meet at the node.

The logic I want to code into the node is as follows:

  • Bot A arrives.
  • IF there is another Bot present at the node (e.g. Bot B)
  • then broker a deal between Bot A and Bot B.
  • ELSE tell Bot A to wait until another Bot arrives at the Node.

My Attempt

Here is my attempt at coding the logic described above.

public void trade(StrippedBot trader)
{
    // check to see if there are any other bots waiting
    if(bots.size() > 0)
    {
        for (StrippedBot b : bots.keySet()) {
            if(!b.equals(trader) && !b.getFamily().getName().equals(trader.getFamily().getName()))
            {
                b.notify();
                trader.getResource().adjust(COOPERATION_REWARD);
                b.getResource().adjust(COOPERATION_REWARD);
                trace(trader);
            }
        }
    } else {
        // this is the first bot here, so shall wait for others to come.
        try
        {
            bots.put(trader, true); // keeping track - true to mean this bot is on wait().
            trader.wait(); // Tell Bot to wait till another bot comes along.
        } catch (InterruptedException e)
        {
            e.printStackTrace();
        }
    }
}

But when I run it, I get the IllegalMonitorStateException on the trader.wait() line. I have researched, and apparently it is a commonly encountered problem. So I tried the synchronized(trader) but that just froze everything, I couldn't even debug through the code, as everything was frozen.

halfer
  • 19,824
  • 17
  • 99
  • 186
J86
  • 14,345
  • 47
  • 130
  • 228
  • It seems to me that (a) you've solved the question in your title and (b) your code is working as designed. wait() waits for another thread to call notify(). – user207421 May 01 '13 at 23:21
  • Try using jconsole to see what your threads are doing or if you have any deadlocks. – Nemanja May 01 '13 at 23:40
  • You should still be able to debug it. Each of the threads that is stopped will show you a pause next to it and you can see where the threads are. That's a good skill to learn. – Gray May 01 '13 at 23:48
  • @EJP: hmm, but I want the `wait()` happening on the bots, not the node. How can I put the bot code in another thread, and then put that new thread to `wait()` ? – J86 May 01 '13 at 23:58
  • @Ciwan Your question doesn't make sense. Objects don't wait. It is *threads* that wait. If you don't want your thread to wait, don't call `wait()`. – user207421 May 02 '13 at 00:22
  • You can tell I'm new to threading. All I know is that a StrippedBot extends `Thread`. So when I call `trader.wait()` which is a StrippedBot, and extends `Thread` I expect only that bot to be put to 'wait()'. Then when needed, I can access its reference and call its `.notify()` method. But it is not working as I have it in my mind. :( – J86 May 02 '13 at 00:28
  • "Put to wait() Thread" doesn't make sense either. It is the *current* thread that waits. You can't wait (or sleep) any thread except the current one. – user207421 May 02 '13 at 00:50

2 Answers2

0

So your code is blocked because you are doing a trader.wait() but no one is doing a trader.notify(). Then again maybe b is a trader. Can't tell from the code. You need to do a notify() on the same exact object you are waiting on in another thread.

I get the IllegalMonitorStateException on the trader.wait() line. I have researched, and apparently it is a commonly encountered problem. So I tried the synchronized(trader)

Right. Do notify() or wait() on an object, you need to be within a synchronized block on that particular object.

  • Remember that the notify() is not stored. If you do a notify() and no one is in the wait() method, then the notify() does nothing.
  • You should be able to debug your code. Eclipse (at least) will show you all of your threads. Scroll up and down until you see one that is paused. You can then expand it and see where it is hung.
  • Feel free to do System.out.println(...) style debugging to see what is going on.

Good luck.

Gray
  • 115,027
  • 24
  • 293
  • 354
  • Thanks Gray. The code never gets inside the first if statement, so whether `b` is a `trader` or not, doesn't apply. Thinking about what EJP said. Do you know how I can place the StrippedBot in a new thread, and tell the new thread to `wait()`? – J86 May 02 '13 at 00:09
  • @Ciwan You can't tell a thread to wait. – user207421 May 02 '13 at 01:24
  • You keep confusing me further and further ^_^ From the Java Docs: `That wait() method Causes the current thread to wait until another thread invokes the notify()` – J86 May 02 '13 at 01:27
  • As I said above, you can cause the *current* thread to wait. You can't cause *another* thread to wait. Basically your design is broken. – user207421 May 02 '13 at 01:39
0

To deal with the IllegalMonitorStateException: You cannot call wait or notify on an unsynchronized object. You must synchronize on the object you wish to call wait or notify on.

But I think your code has other issues, for example, if you wait on trader, you'll want to notify on trader. And, I suspect there are even more issues, but I'll restrict my answer to addressing the OPs direct question.

xagyg
  • 9,562
  • 2
  • 32
  • 29