it is clear that the method, as implemented by Sun, does not simply yield time to the specified thread, but actually it first attempts to obtain a monitor on the thread object.
It doesn't yield to the thread joined, it just waits with the assumption that at some point the thread will run to completion. Having a join() on a thread does not make it more likely to run than any other thread ready to run.
- If N threads all attempt to join the same thread, and they all specify the same timeout T, then one of the threads will end up waiting at least N*T ms. In other words, each thread has to "wait its turn" to execute its wait. Is it reasonable for separate threads to execute joins serially instead of in parallel?
Threads are designed to work concurrently. If they all wait, they do so concurrently. A waiting thread does not make another thread wait longer.
.2. It is possible that a thread which enters a join with a nonzero timeout may never return.
not unless you intend this to happen.
This is because there is no guarantee the monitor will ever become available.
The situation you suggest could only occur if a thread obtains a lock on the thread and then holds it forever without waiting. This is a programming bug. IMHO You should never obtain a lock on a thread object directly.
If a thread obtains its own monitor before blocking on an I/O operation, and that operation hangs, then any thread which attempts to join the thread will also hang.
Java doesn't protect you from malicious code in your own JVM.
Is it reasonable for an operation with an explicit time out to hang indefinitely?
If it is being locked out indefinitely, yes.
.3. In order to write a correct program which uses the method, the caller must know in advance whether the target thread or some other thread could be holding the monitor.
Don't ever lock the thread object, there is no reason you should need to, and you won't have this problem. If you want to start looking at every way you could confuse other developers or yourself, then Threads isn't the place you would start IMHO.
For example, consider what happens if thread 1 is performing some sort of processing work, then thread 2 joins thread 1 with a timeout of 0, and then thread 3 attempts to join thread 1 with a timeout of 10 ms. The 0 timeout join means that thread 2 will wait until thread 1 exits. But thread 3 cannot begin its wait until thread 2 releases the monitor,
Thread 2 releases the monitor as soon as wait is called. It cannot wait and hold the monitor at the same time.
so effectively thread 3's wait of 10 ms was silently converted to an indefinite wait, which was not what the caller intended.
no. see previous comments.
Doesn't requiring the caller to know details about the implementation violate the principle of encapsulation?
It would.
.4. If a thread is blocked because it cannot obtain the monitor, it is not interruptible, and will not throw the InterruptedException as described in the documentation. So not only might a thread wait longer than expected, or even indefinitely, it may become completely unresponsive, causing the entire program to hang. Is it reasonable for an interruptible operation to become unresponsive?
yes. But this is a very rare condition. If you use the code as written, the situation you refer to will only exist for a few milli-seconds at most.
Overall, it seems inappropriate to make the operation of a timeout dependent on obtaining a monitor, unless it can be guaranteed that the task of obtaining the monitor will itself time out. Is thread join broken?
You can do what you suggest with the more recent Java 5 concurrency libraries.
However, I suggest you shouldn't assume that timeouts are guaranteed to be milli-second accurate. currentTimeMillis() used by this method is only accurate to about 16 ms on Windows XP and wait/sleep is typically 2 ms longer than it should be for small timeouts on Linux.
IMHO If you need accuracy of more than 40 ms you may have difficulty, however if you work around this you will find this doesn't have to be a problem.