1

My code has a UI thread that updates a Boolean variable. The problem I'm having is I want the main program to continuing executing when the variable becomes true.

public static void main(String[] args) throws Exception{
//Display the UI by creating an instance of Node
Node node = new Node();

//Wait for the node to connect to a router before continuing
while(!isConnectedToRouter);

//Do other things
}

While debugging I noticed the main thread suspends itself so main never gets to "Do other things". Even after another thread makes the boolean isConnectedToRouter true. If i change the while loop to

//Wait for the node to connect to a router before continuing
while(!isConnectedToRouter){
    Thread.sleep(1);
}

It works, but It makes me aware that I'm doing something wrong. Any help would be appreciated.

Bhopewell
  • 57
  • 6
  • 2
    Is `isConnectedToRouter` declared as `volatile`? – nikis Mar 25 '15 at 20:43
  • No, it's "private static boolean" – Bhopewell Mar 25 '15 at 20:44
  • 3
    It *should* be `volatile`, otherwise changing the value in another thread is never guaranteed to become visible in the main thread. Anyway, busy looping is rarely a good idea. It's better wait until the other thread is ready, and let it wake up the main thread when done. – kiheru Mar 25 '15 at 20:54
  • Thanks guys, making the Boolean volatile made it work. I guess the main thread cached its value. I've never used volatile before but it makes sense now. As for the other advice I can see why busy waiting is bad design but it's what I have to work with now. I'll keep that in mind though. Thank you. – Bhopewell Mar 25 '15 at 21:10
  • 2
    Avoiding the busy wait is not very difficult: you could use the low level primitives from Object [wait/notify/notifyAll](http://stackoverflow.com/questions/886722/how-to-use-wait-and-notify-in-java) or use the higher level interfaces from `java.util.concurrent`. – kiheru Mar 25 '15 at 21:23
  • @kiheru You should flesh that out into an answer. It's the right answer. – zwol Mar 25 '15 at 21:50
  • This thread is not suspended. It is running, and producing smoke from the CPU. – user207421 Mar 25 '15 at 22:34

2 Answers2

2

Better than busy waiting is sleeping in the main thread until it's time to continue.

java.util.concurrent has high level level interfaces for threading that are easier to use safely and fit most situations.

Waiting using CountDownLatch for example could be done like:

CountDownLatch latch = new CountDownLatch(1);

, this object should be visible in both the main thread and in your worker. Locking needs to be made using the same object.

Waiting in the main thread:

latch.await();

And when the other thread is ready:

latch.countDown();

This implementation has the advantage that you don't need to worry about the case where the worker thread is ready before the waiting phase is started. In that situation the await() does the right thing and returns immediately.

In this situation the old low level methods from Object could also be used, but special care would be needed to handle the case where the worker thread is ready before the main thread would wait - without checking that it would be easy to lock up the main thread. So I recommend to sticking java.util.concurrent, unless you have good reasons to not to. Those classes exist to help writing safe threading code.

note: I left out the code handling InterruptedExceptions for brevity - that should be done both with latch.wait() and Object.wait()

kiheru
  • 6,588
  • 25
  • 31
0

YOU should make the boolean volatle in order that the main thread can read the latest value of that boolean variable, rather than just reading the values in registers.

baiyb
  • 11
  • 3