Are these Threads synchronized? - java

My task is to create x Threads, and in some way to use MethodA and B, and synchronize them, and to catch some Exception in the end.
I know this is not a really good description of the task, but this is how I got the task.
So the question is, would this code do, what the task is asking for?
Are these Threads synchronized correctly or not?
public class Test2{
public static synchronized void doActionA(){
System.out.println("Hi");
}
public static synchronized void doActionB(){
System.out.println("Hello");
}
public static void main(String[] args) {
for(int i = 0; i < 10000; ++i){
try{
new Thread(() -> {
doActionA();
doActionB();
}).start();
}catch(Exception e){
e.printStackTrace();
}finally{
System.out.println(":)");
}
}
}
}

This is mostly useless, yeah.
You have 10000 threads. Each thread is going to perform the following task pattern:
NB: Take the object "Test2.class" (the instance of java.lang.Class that represents the Test2 class; there is only one such object in the entire VM loaded. We shall call this 'the locker'.
Check the locker object for its 'monitor' thread. If it is unset, set yourself as the monitor thread of the locker and continue. (and do all that atomically). If not, freeze the thread until the 'monitor' is null again, and then compete with the 9999 other threads that want to set it; only one of the 9999 wins, sets itself as the monitor, and continues. The remainining 9998 will freeze and wait another round.
Execute doActionA. All the while, 9999 threads are twiddling thumbs.
Relinquish the locker (unset yourself as the monitor of the locker). 9999 other threads all fly in to set themselves as monitor. Only one of those will 'win'.
Acquire the lock again (set yourself as the monitor of the locker if it is currently unset; otherwise, freeze and wait until it is available.. and do that atomically). Depending on the JVM implementation, this thread may in fact 'win', and take the monitor riiight back, beating the other 9999 threads.
Execute doActionB. During this job, 9999 threads are twiddling thumbs doing absolutely nothing whatsoever. Just waiting around.
Relinquish the monitor and exit. Pfew. 9999 more to go.
As you can tell, this pattern most likely means this code runs as fast as just:
for (int i = 0; i < 10000; i++) {
doActionA();
doActionB();
}
except the above most likely runs FAR faster, as your example first allocates 1.25 gigabytes worth of memory just to store stacks (each thread needs a stack, and here's praying your stacks are 'just' 128k large, they are often larger), and wastes a ton of time juggling thread states for pretty much no purpose.
This is not how you thread things.

Are these Threads synchronized correctly or not?
"Synchronized" in what way? "Synchronized" for what purpose?
It's "correct" if the program is guaranteed to do what you want it to do. What do you want this program to do?
What it will do is, it will print print ten thousand complete lines of "Hi", and it will print ten thousand complete lines of "Hello", and it will print them in no particular order. The reason each line will be complete is that the System.out object uses synchronization to ensure that at most one thread at a time can execute println(...). The reason why the lines will be printed in no particular order is, there isn't any other synchronization between the threads in the program.

This is the main part of your task:
catch some Exception in the end.
The question is: would this code do what the task is asking for?
No, becasue exception happened inside a thread can not be caught outside of the thread like this, read the following question for more information:
How to catch an Exception from a thread

Related

If java normal threads don't call "join", does it lead to unknown behavior before finish?

Normal java threads, not daemon threads, seem to execute till end, then main thread finishes, like this:
public static void main(String[] args) {
for(int i = 0; i < 3; ++i){
new Thread(new Runnable(){
#Override
public void run() {
try {
Thread.sleep(2000);
System.out.println("Does this still print?");
} catch (Exception e) {
e.printStackTrace();
}
}
}).start();
}
// Java normal threads don't have to call join, they'll still wait to finish.
System.out.println("Main thread start");
}
It will print:
Main thread start
i = 2
i = 0
i = 1
Does this still print?
Does this still print?
Does this still print?
What I saw here is, Java normal threads don't have to call join() and their holder still wait for them to finish. Not sure if my program is too simple to encounter any undefined behavior, could you kindly give some hints when should we use join()?
Thanks.
t.join() does not do anything to thread t in Java. All it does is not return until thread t has finished.
A Java program's main() thread does not wait for any other thread to finish after main() returns. It just ends, and any other non-daemon threads keep running.
Java is not like Go. In Go the program continues only as long as the main thread is alive, in Java any living nondaemon thread keeps the jvm around. In your code the main thread kicks off other threads and then dies. The new threads run to completion even though the main thread is long gone.
For "undefined behavior" I'm guessing you mean data races, or memory visibility issues, where you can't rely on one thing happening before another (for races) or on a value being visible across threads (for vidibility). Calling join does create a happens-before edge. So does calling println (since it acquires a lock). The Java language spec has a list of things that create a happens-before edge.
Calling get on a Future blocks until the future is done similar to how calling join on a Thread blocks until the thread is finished. If you use higher level constructs than just threads, whether it's executor services, CompletableFuture, reactive libraries, actor systems, or other concurrency models, then those are to different extents shielding you from the Thread api and you don't need join so much.

Why code from main method executes before other Threads in java

I have Main class with main method. I create two Threads What i noticed that code from main thread executes before created Threads. What i was expecting is to run it simultaneous. Why code from main method executes berofe code from Threads?
Main.class:
public class Main extends Thread {
public static void main(String[] args) {
NewThread thread = new NewThread("Thread1");
NewThread thread2 = new NewThread("Thread2");
for (int i = 0; i <3 ; i++) {
System.out.println("From main thread");
}
thread.start();
thread2.start();
}
}
NewThread.class
public class NewThread extends Thread{
public NewThread(String name) {
this.setName(name);
}
public void run() {
int clientnumber = 1;
while(clientnumber!= 3) {
System.out.println("server sent data to client: " + getName());
clientnumber++;
}
}
}
Output:
From main thread
From main thread
From main thread
server sent data to client: Thread2
server sent data to client: Thread1
server sent data to client: Thread2
server sent data to client: Thread1
Why code from main method executes before code from Threads?
Simply, because it can.
When you start() a thread, either the parent thread or the child thread may be scheduled to run next. Or they may both scheduled simultaneously. Or an entirely different thread may be scheduled.
The Java language and runtime system make no guarantees of thread scheduling order. Furthermore thread scheduling behavior is liable to be different for different execution platforms1; e.g. depending on how many cores you have.
(Why? Because, this is how native thread scheduling works on a typical OS. Java can't fight this and still use native threads. Using user-space threads and thread scheduling has serious performance issues. Sun abandoned that approach decades ago.)
What do you do to solve this?
Don't make assumptions about scheduling, and the order in which threads will execute.
If your application really needs one thread to run before the other, use one of the concurrency primitives or classes to achieve it ... explicitly. (But beware that by forcing one thread to run before another you are reducing the effective concurrency.)
In your example, the problem is basically that your expectations were incorrect. It is no longer a problem once you have adjusted your expectations.
1 - Behavior is likely to be repeatable on a given platform, especially in a small / simple example like yours. But then again, it could change if you ran your test while the system was under heavy load. Remember: No guarantees!
Execution of other threads starts with .start() method - you call this method after loop printing informations to the console in `main.
EDIT: These lines are printed before lines from new threads, because it is likely to be faster to print 3 lines to the console than perform loops in other threads and then print. After edit that you made to the question - to see how all three threads (including thread containing main()) are working in the same time and to see the difference in order of printed lines - I suggest you to try one of the following ways to see the difference:
Try to perform time-consuming operation in main() after starting new threads and before printing to the console in main() (you can think of that operation on your own or try one of these listed in these answers, or
Try to increase number of loops (maybe even to few thousands) with statements printing to the console in each thread - you'll see that all threads work in the same time, or
Simply call Thread.sleep(1000) (or higher number as the argument - it's number of milliseconds that you want the current thread to sleep) in main() after starting new threads and before printing lines from the main().
NewThread thread has to be started before it will start executing. You are starting both threads only after main() has processed the loop. What you want is probably:
new NewThread("Thread1").start();
new NewThread("Thread2").start();
for (int i = 0; i <3 ; i++) {
System.out.println("From main thread");
}
However it's up to JVM and OS to schedule the threads. You still might observer the main() executing first before NewThread gets a chance to run.

What are the main uses of yield(), and how does it differ from join() and interrupt()?

I am a little bit confused about the use of Thread.yield() method in Java, specifically in the example code below. I've also read that yield() is 'used to prevent execution of a thread'.
My questions are:
I believe the code below result in the same output both when using yield() and when not using it. Is this correct?
What are, in fact, the main uses of yield()?
In what ways is yield() different from the join() and interrupt() methods?
The code example:
public class MyRunnable implements Runnable {
public static void main(String[] args) {
Thread t = new Thread(new MyRunnable());
t.start();
for(int i=0; i<5; i++) {
System.out.println("Inside main");
}
}
public void run() {
for(int i=0; i<5; i++) {
System.out.println("Inside run");
Thread.yield();
}
}
}
I obtain the same output using the code above both with and without using yield():
Inside main
Inside main
Inside main
Inside main
Inside main
Inside run
Inside run
Inside run
Inside run
Inside run
Source: http://www.javamex.com/tutorials/threads/yield.shtml
Windows
In the Hotspot implementation, the way that Thread.yield() works has
changed between Java 5 and Java 6.
In Java 5, Thread.yield() calls the Windows API call Sleep(0). This
has the special effect of clearing the current thread's quantum and
putting it to the end of the queue for its priority level. In other
words, all runnable threads of the same priority (and those of greater
priority) will get a chance to run before the yielded thread is next
given CPU time. When it is eventually re-scheduled, it will come back
with a full full quantum, but doesn't "carry over" any of the
remaining quantum from the time of yielding. This behaviour is a
little different from a non-zero sleep where the sleeping thread
generally loses 1 quantum value (in effect, 1/3 of a 10 or 15ms tick).
In Java 6, this behaviour was changed. The Hotspot VM now implements
Thread.yield() using the Windows SwitchToThread() API call. This call
makes the current thread give up its current timeslice, but not its
entire quantum. This means that depending on the priorities of other
threads, the yielding thread can be scheduled back in one interrupt
period later. (See the section on thread scheduling for more
information on timeslices.)
Linux
Under Linux, Hotspot simply calls sched_yield(). The consequences of
this call are a little different, and possibly more severe than under
Windows:
a yielded thread will not get another slice of CPU until all other threads have had a slice of CPU;
(at least in kernel 2.6.8 onwards), the fact that the thread has yielded is implicitly taken into account by the scheduler's heuristics
on its recent CPU allocation— thus, implicitly, a thread that has
yielded could be given more CPU when scheduled in the future.
(See the section on thread scheduling for more details on priorities
and scheduling algorithms.)
When to use yield()?
I would say practically never. Its behaviour isn't standardly defined
and there are generally better ways to perform the tasks that you
might want to perform with yield():
if you're trying to use only a portion of the CPU, you can do this in a more controllable way by estimating how much CPU the thread
has used in its last chunk of processing, then sleeping for some
amount of time to compensate: see the sleep() method;
if you're waiting for a process or resource to complete or become available, there are more efficient ways to accomplish this,
such as by using join() to wait for another thread to complete, using
the wait/notify mechanism to allow one thread to signal to another
that a task is complete, or ideally by using one of the Java 5
concurrency constructs such as a Semaphore or blocking queue.
I see the question has been reactivated with a bounty, now asking what the practical uses for yield are. I'll give an example from my experience.
As we know, yield forces the calling thread to give up the processor that it's running on so that another thread can be scheduled to run. This is useful when the current thread has finished its work for now but wants to quickly return to the front of the queue and check whether some condition has changed. How is this different from a condition variable? yield enables the thread to return much quicker to a running state. When waiting on a condition variable the thread is suspended and needs to wait for a different thread to signal that it should continue. yield basically says "allow a different thread to run, but allow me to get back to work very soon as I expect something to change in my state very very quickly". This hints towards busy spinning, where a condition can change rapidly but suspending the thread would incur a large performance hit.
But enough babbling, here's a concrete example: the wavefront parallel pattern. A basic instance of this problem is computing the individual "islands" of 1s in a bidimensional array filled with 0s and 1s. An "island" is a group of cells that are adjacent to eachother either vertically or horizontally:
1 0 0 0
1 1 0 0
0 0 0 1
0 0 1 1
0 0 1 1
Here we have two islands of 1s: top-left and bottom-right.
A simple solution is to make a first pass over the entire array and replace the 1 values with an incrementing counter such that by the end each 1 was replaced with its sequence number in row major order:
1 0 0 0
2 3 0 0
0 0 0 4
0 0 5 6
0 0 7 8
In the next step, each value is replaced by the minimum between itself and its neighbours' values:
1 0 0 0
1 1 0 0
0 0 0 4
0 0 4 4
0 0 4 4
We can now easily determine that we have two islands.
The part we want to run in parallel is the the step where we compute the minimums. Without going into too much detail, each thread gets rows in an interleaved manner and relies on the values computed by the thread processing the row above. Thus, each thread needs to slightly lag behind the thread processing the previous line, but must also keep up within reasonable time. More details and an implementation are presented by myself in this document. Note the usage of sleep(0) which is more or less the C equivalent of yield.
In this case yield was used in order to force each thread in turn to pause, but since the thread processing the adjacent row would advance very quickly in the meantime, a condition variable would prove a disastrous choice.
As you can see, yield is quite a fine-grain optimization. Using it in the wrong place e.g. waiting on a condition that changes seldomly, will cause excessive use of the CPU.
Sorry for the long babble, hope I made myself clear.
About the differences between yield(), interrupt() and join() - in general, not just in Java:
yielding: Literally, to 'yield' means to let go, to give up, to surrender. A yielding thread tells the operating system (or the virtual machine, or what not) it's willing to let other threads be scheduled in its stead. This indicates it's not doing something too critical. It's only a hint, though, and not guaranteed to have any effect.
joining: When multiple threads 'join' on some handle, or token, or entity, all of them wait until all other relevant threads have completed execution (entirely or upto their own corresponding join). That means a bunch of threads have all completed their tasks. Then each one of these threads can be scheduled to continue other work, being able to assume all those tasks are indeed complete. (Not to be confused with SQL Joins!)
interruption: Used by one thread to 'poke' another thread which is sleeping, or waiting, or joining - so that it is scheduled to continue running again, perhaps with an indication it has been interrupted. (Not to be confused with hardware interrupts!)
For Java specifically, see
Joining:
How to use Thread.join? (here on StackOverflow)
When to join threads?
Yielding:
Interrupting:
Is Thread.interrupt() evil? (here on StackOverflow)
First, the actual description is
Causes the currently executing thread object to temporarily pause and
allow other threads to execute.
Now, it is very likely that your main thread will execute the loop five times before the run method of the new thread is being executed, so all the calls to yield will happen only after the loop in the main thread is executed.
join will stop the current thread until the thread being called with join() is done executing.
interrupt will interrupt the thread it is being called on, causing InterruptedException.
yield allows a context switch to other threads, so this thread will not consume the entire CPU usage of the process.
The current answer(s) are out-of-date and require revision given recent changes.
There is no practical difference of Thread.yield() between Java versions since 6 to 9.
TL;DR;
Conclusions based on OpenJDK source code (http://hg.openjdk.java.net/).
If not to take into account HotSpot support of USDT probes (system tracing information is described in dtrace guide) and JVM property ConvertYieldToSleep then source code of yield() is almost the same. See explanation below.
Java 9:
Thread.yield() calls OS-specific method os::naked_yield():
On Linux:
void os::naked_yield() {
sched_yield();
}
On Windows:
void os::naked_yield() {
SwitchToThread();
}
Java 8 and earlier:
Thread.yield() calls OS-specific method os::yield():
On Linux:
void os::yield() {
sched_yield();
}
On Windows:
void os::yield() { os::NakedYield(); }
As you can see, Thread.yeald() on Linux is identical for all Java versions.
Let's see Windows's os::NakedYield() from JDK 8:
os::YieldResult os::NakedYield() {
// Use either SwitchToThread() or Sleep(0)
// Consider passing back the return value from SwitchToThread().
if (os::Kernel32Dll::SwitchToThreadAvailable()) {
return SwitchToThread() ? os::YIELD_SWITCHED : os::YIELD_NONEREADY ;
} else {
Sleep(0);
}
return os::YIELD_UNKNOWN ;
}
The difference between Java 9 and Java 8 in the additional check of the existence of the Win32 API's SwitchToThread() method. The same code is present for Java 6.
Source code of os::NakedYield() in JDK 7 is slightly different but it has the same behavior:
os::YieldResult os::NakedYield() {
// Use either SwitchToThread() or Sleep(0)
// Consider passing back the return value from SwitchToThread().
// We use GetProcAddress() as ancient Win9X versions of windows doen't support SwitchToThread.
// In that case we revert to Sleep(0).
static volatile STTSignature stt = (STTSignature) 1 ;
if (stt == ((STTSignature) 1)) {
stt = (STTSignature) ::GetProcAddress (LoadLibrary ("Kernel32.dll"), "SwitchToThread") ;
// It's OK if threads race during initialization as the operation above is idempotent.
}
if (stt != NULL) {
return (*stt)() ? os::YIELD_SWITCHED : os::YIELD_NONEREADY ;
} else {
Sleep (0) ;
}
return os::YIELD_UNKNOWN ;
}
The additional check has been dropped due to SwitchToThread() method are available since Windows XP and Windows Server 2003 (see msdn notes).
What are, in fact, the main uses of yield()?
Yield suggests to the CPU that you may stop the current thread and start executing threads with higher priority. In other words, assigning a low priority value to the current thread to leave room for more critical threads.
I believe the code below result in the same output both when using yield() and when not using it. Is this correct?
NO, the two will produce different results. Without a yield(), once the thread gets control it will execute the 'Inside run' loop in one go. However, with a yield(), once the thread gets control it will print the 'Inside run' once and then will hand over control to other thread if any. If no thread in pending, this thread will be resumed again. So every time "Inside run' is executed it will look for other threads to execute and if no thread is available, the current thread will keep on executing.
In what ways is yield() different from the join() and interrupt() methods?
yield() is for giving room to other important threads, join() is for waiting for another thread to complete its execution, and interrupt() is for interrupting a currently executing thread to do something else.
Thread.yield() causes thread to go from "Running" state to "Runnable" state.
Note: It doesn't cause thread to go "Waiting" state.
Thread.yield(); frees the bottom thread.
Thread is using OS threads, so Thread.yield(); might free the hardware thread.
Bad implementation for sleep(millis)
public class MySleep {
public static void sleep(long millis) throws InterruptedException {
long start = System.currentTimeMillis();
do {
Thread.yield();
if (Thread.interrupted()) {
throw new InterruptedException();
}
} while (System.currentTimeMillis() - start < millis);
}
}
and join()
public class MyJoin {
public static void join(Thread t) throws InterruptedException {
while (t.getState() != Thread.State.TERMINATED) {
Thread.yield();
if (Thread.interrupted()) {
throw new InterruptedException();
}
}
}
public static void main(String[] args) {
Thread thread = new Thread(()-> {
try {
Thread.sleep(2000);
} catch (Exception e) {
}
});
thread.start();
System.out.println("before");
try {
join(thread);
} catch (Exception e) {
}
System.out.println("after");
}
}
This should work even if there is only one hardware thread, unless Thread.yield(); is removed.
Thread.yield()
When we invoke Thread.yield() method, the thread scheduler keep the currently running thread to Runnable state and picks another thread of equal priority or higher priority. If there is no equal and higher priority thread then it reschedule the calling yield() thread. Remember yield method does not make the thread to go to Wait or Blocked state. It can only make a thread from Running State to Runnable State.
join()
When join is invoked by a thread instance, this thread will tell currently executing thread to wait till the Joining thread completes. Join is used in the situations when a task which should be completed before the current task is going to finish.
yield() main use is for putting a multi-threading application on hold.
all these methods differences are yield() puts thread on hold while executing another thread and returning back after the completion of that thread, join() will bring the beginning of threads together executing until the end and of another thread to run after that thread has ended, interrupt() will stop the execution of a thread for a while.

Synchronizing threads in java

Good day!
I got the problem about synchronizing threads in java. I am developing program which creates timers and allows to reset it, delete and stop. Just to learn how to using threads.
The problem is that code gives synchronizing only for some time... I can't understand my mistake. Maybe my way is wrong so i would like to know how to solve this issue.
I have next code:
public class StopWatch
{
//Create and start our timer
public synchronized void startClock( final int id )
{
//Creating new thread.
thisThread = new Thread()
{
#Override
public void run()
{
try
{
while( true )
{
System.out.printf( "Thread [%d] = %d\n", id, timerTime );
timerTime += DELAY; //Count 100 ms
Thread.sleep( DELAY );
}
}
catch( InterruptedException ex )
{
ex.printStackTrace();
}
}
};
thisThread.start();
}
…
//Starting value of timer
private long timerTime = 0;
//Number of ms to add and sleep
private static final int DELAY = 100;
private Thread thisThread;
}
I call this Class like:
StopWatch s = new StopWatch(1);
s.startClock();
StopWatch s2 = new StopWatch(2);
s2.startClock();
I think you may have misunderstood "synchronized".
It does not mean that the threads run in exactly synchronized time - rather that only one thread at a time is allowed to be executing the synchronized code block. In your case "synchronized" makes no difference, since you are calling the startClock method from the same thread....
In general, it is impossible in Java (and indeed most high level languages) to guarantee that two threads perform actions at exactly the same clock time even if you have multiple cores, since they are always vulnerable to being delayed by the OS scheduler or JVM garbage collection pauses etc.
Also, Thread.sleep(...) is unreliable as a timing mechanism, as the amount it sleeps for is only approximate. You're at the mercy of the thread scheduler.
Suggested solution:
use System.currentTimeMillis() if you want a thread-independent timing mechansim.
What do you mean it "only gives you synchronizing for some time?" The only thing you have synchronized here is the startClock method, which just means that two threads will not be within that method at the same time (and it doesn't look like you are doing that anyway). If you wanted to synchronize access to timerTime for example, you would need to put a synchronized block inside thread run method around the incrementing timerTime (or you could use an AtomicLong).
You should probably re-read the documentation for the "synchronize" keyword. I'm pretty sure in this case all it would do is keep the two calls of StartClock() from executing at the same time, which wouldn't happen given this code because they're called one after the other from one thread. Once the timer thread begins, there's nothing keeping them synchronized, if that's your goal.
Your first problem is that this is a time based only solution. This is bad because the program has no control over how long it takes to execute. Some operations take more time than others and each thread within your process doesn't execute at the same time. In general this won't synchronize anything unless you can guarantee everything else is the same . . .
Read about http://download.oracle.com/javase/6/docs/api/java/util/concurrent/Semaphore.html and you can also do
Thread.join(); to make the main loop wait for the execution of the child thread to finish before continuing execution.
I think you misunderstood what synchronized means. Synchronized is to ensure that multiple threads have limited access to a certain block of code so that you don't get conflicts between the two threads.
I think what you may be more interested in is a CyclicBarrier or a CountDownLatch. Both can be used to "synchronize" (overloaded use in this case) multiple threads so that they try to start doing things at the same time.
However, be aware that it's impossible to have multiple threads do things at exactly the same instant. You can only try to encourage to do them at about the same time. The rest is subject to OS scheduling on the cores in the system. And if you have a single core, they will never run at the same time.

Is Sun's Thread.join method broken because it synchronizes usng the Thread object?

By both running test programs and looking at source code, 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. Specifically, the method is implemented as "synchronized."
Note that the wait and notify methods also require the monitor, but unlike join, it is the caller's responsibility to obtain the monitor before making the call, and the documentation clearly says so. The fact that join depends on the monitor is not documented in the Javadocs, although perhaps it is natural to make the inference.
Is the documentation clear enough?
Additionally, if the thread can't obtain the monitor for some reason, it will hang, maybe forever. While waiting for the monitor, a thread is not interruptible, and will not throw the InterruptedException as described in the documentation. On the other hand, it is not clear why a thread wouldn't be able to obtain the monitor except in the case of a programming error.
Is it reasonable to worry about contention over the monitor?
Finally, 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 depending on the monitor for join() a reasonable implementation? Is it even possible to implement it any other way?
Thread.join calls wait, which releases the monitor. As this means a "joining" thread doesn't block any other thread from calling join as well, I suspect this answers most of your other queries. It doesn't prevent another caller from synchronizing on the thread's monitor (oh the joys of public monitors) but it means that the common case works fine.
Just to demonstrate that your first point is wrong, here's an example which creates 10 threads which each wait on the main thread for 5 seconds. (Please ignore the horrible exception swallowing and abuse of Date. It's only intended to be used to study the threading behaviour.)
import java.util.*;
public class Test
{
public static void main(String[] args) throws Exception
{
for (int i=0; i < 10; i++)
{
new Thread(new ThreadJoiner(Thread.currentThread(), i))
.start();
}
try
{
Thread.sleep(10000);
}
catch (InterruptedException e) {}
}
private static class ThreadJoiner implements Runnable
{
private final Thread threadToJoin;
int id;
public ThreadJoiner(Thread threadToJoin, int id)
{
this.threadToJoin = threadToJoin;
this.id = id;
}
public void run()
{
try
{
System.out.println("Thread " + id +
" waiting at " + new Date());
threadToJoin.join(5000);
System.out.println("Thread " + id +
" finished waiting at " + new Date());
}
catch (InterruptedException e) {}
}
}
}
If you run that, you'll see that all the threads start and end their waits virtually simultaneously. You don't get the ends "staggered" as you would if your concerns were well-founded.
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.

Categories