4
while(!anotherThread.isDone());

or

while(!anotherThread.isDone())
    Thread.sleep(5);
Richard J. Ross III
  • 55,009
  • 24
  • 135
  • 201
Vig
  • 1,532
  • 1
  • 12
  • 28
  • I believe he isn't waiting for the other Thread to be finished, he's waiting for it to signal completion of some task. So Thread.join() is inappropriate. Maybe you could be more specific about what you're trying to do Vig? – jlewis42 Feb 13 '12 at 17:18
  • @jlewis42 I'm completely aware of using Thread.join methods I just wanted to know if using while(!anotherThread.isDone()); will chew lot of processing vice while(!anotherThread.isDone()) Thread.sleep(5); – Vig Feb 13 '12 at 17:46
  • 1
    In that case the one that sleeps will definitely be better. The one that doesn't sleep will just keep checking and worse yet, compete with your working thread for computing resources. – jlewis42 Feb 13 '12 at 18:13
  • 1
    @jlewis42 no, no, no, please don't encourage developers to use sleep() loops for inter-thread comms! This is so prevalent that sleep() is now widely described by experienced developers as an anti-pattern, even though it has valid uses, (and inter-thread comms is not one of them). – Martin James Feb 13 '12 at 19:14
  • @Martin James What do you think about using Thread.yield() instead of sleep? – jlewis42 Feb 13 '12 at 23:00

8 Answers8

6

If you really need to wait for a thread to complete, use

anotherThread.join()

(You may want to consider specifying a timeout in the join call.)

You definitely shouldn't tight-loop like your first snippet does... and sleeping for 5ms is barely better.

If you can't use join (e.g. you're waiting for a task to complete rather than a whole thread) you should look at the java.util.concurrent package - chances are there's something which will meet your needs.

Jon Skeet
  • 1,421,763
  • 867
  • 9,128
  • 9,194
  • 1
    'and sleeping for 5ms is barely better' - it's hugely worse. It has all the context-change overhead of blocking signalling, but no priority-boost on boolean set and also comes with an added 2.5ms average latency, (and that's assuming that a 5ms sleep is even slightly accurate). It's designs like that that make some developers post about sleep() being an anti-pattern! – Martin James Feb 13 '12 at 19:08
5

IMHO, avoid using such logic altogether. Instead, perhaps implement some sort of notification system using property change listeners.

mre
  • 43,520
  • 33
  • 120
  • 170
3

I would recommend utilizing the wait/notify mechanism that is built into all Java objects (or using the new Lock code in Java 5).

Thread 1 (waiting for Thread2)

while(!thread2.isDone()) {
  synchronize(thread2.lockObject) {
    thread2.lockObject.wait();
  }
}

Thread 2

// finish work, set isDone=true, notify T1
thread2.lockObject.notify();

'lockObject' is just a plain (Object lockObject = new Object()) -- all Java objects support the wait/notify calls.

After that last call to notify(), Thread1 will wake up, hit the top of the while, see that T2 is now done, and continue execution.

You should account for interrupt exceptions and the like, but using wait/notify is hugely helpful for scenarios like this.

If you use your existing code, with or without sleep, you are burning a huge number of cycles doing nothing... and that's never good.

ADDENDUM

I see a lot of comments saying to use join - if the executing thread you are waiting on will complete, then yes, use join. If you have two parallel threads that run at all times (e.g. a producer thread and a consumer) and they don't "complete", they just run in lock-step with each other, then you can use the wait/notify paradigm I provided above.

Riyad Kalla
  • 10,604
  • 7
  • 53
  • 56
3

As others have said, it's better to just use join in this case. However, I'd like to generalize your question and ask the following:

In general when a thread is waiting for an event that depends on another thread to occur is it better to:

  1. Use a blocking mechanism (i.e. join, conditional variable, etc.) or
  2. Busy spin without sleep or
  3. Busy spin with sleep?

Now let's see what are the implications for each case:

  1. In this case, using a blocking call will effectively take your thread off the CPU and not schedule it again until the expected event occurs. Good for resource utilization (the thread would waste CPU cycles otherwise), but not very efficient if the event may occur very frequently and at small intervals (i.e. a context switch is much more time-consuming than the time it takes for the event to occur). Generally good when the event will occur eventually, but you don't know how soon.
  2. In case two, you are busy spinning, meaning that you are actively using the CPU without performing useful work. This is the opposite of case 1: it is useful when the event is expected to occur very very soon, but otherwise may occupy the CPU unnecessarily.
  3. This case is a sort of trade-off. You are busy spinning, but at the same time allowing other threads to run by giving up the CPU. This is generally employed when you don't want to saturate the CPU, but the event is expected to occur soon and you want to be sure that you will still be there in almost real time to catch it when it occurs.
Tudor
  • 61,523
  • 12
  • 102
  • 142
  • 4
    3) - Busy spin with sleep() is completely hopeless. It has all the disadvantages of 1) with added latency of, on average, interval/2. Use kernel synchronization, (ie. 1), or just loop, (ie. 2). – Martin James Feb 13 '12 at 19:03
1

The second one.

Better though is to use the join() method of a thread to block the current thread until it is complete :).

EDIT:

I just realised that this only addresses the question as it applies to the two examples you gave, not the question in general (how to wait for a boolean value to be changed by another Thread, not necessarily for the other Thread to actually finish).

To answer the question in general I would suggest that rather than using the methods you described, to do something like this I would recommend using the guarding block pattern as described here. This way, the waiting thread doesn't have to keep checking the condition itself and can just wait to be notified of the change. Hope this helps!

Elias Vasylenko
  • 1,524
  • 11
  • 21
0

Have you considered: anotherThread.join() ? That will cause the current one to be 'parked' without any overhead until the other one terminates.

andrewmu
  • 14,276
  • 4
  • 39
  • 37
0

The second is better than the first, but neither is very good. You should use anotherThread.join() (or anotherThread.join(timeout)).

Ted Hopp
  • 232,168
  • 48
  • 399
  • 521
0

Neither, use join() instead:

anotherThread.join();
// anotherThread has finished executing.
Richard J. Ross III
  • 55,009
  • 24
  • 135
  • 201