Reputation: 2198
My Code
public class Main {
public static void main(String[] args)throws Exception {
Thread thread1=new Thread(new Runnable()
{
public void run()
{
System.out.println("Thread1");
}
});
thread1.join();
thread1.start();
for (int i = 0; i < 1000; i++) {
System.out.println(i);
}
}
}
Sometimes "Thread1" gets printed even before all the numbers get printed. Any reason for that? Shouldn't Thread1 should wait until main thread gets completed?
Upvotes: 1
Views: 3794
Reputation: 57
Actually, we should make sure the system has started the thread in accordance with our ".start()" request (which doesn't necessarily happen before start() returns), before invoking join(), as join() does not really wait until a thread dies, rather, it simply returns as soon as a thread isn't running. This can happen before the thread starts, or after it finishes. See "Taming Java Threads" by Allen Holub, page 87. Here is what I feel is the correct way to write this code:
import java.util.concurrent.Semaphore;
public class Main {
public static void main(String[] args)throws Exception {
final Semaphore waitForThreadToStart = new Semaphore (0);
Thread thread1=new Thread(new Runnable()
{
public void run()
{
waitForThreadToStart.release();
System.out.println("Thread1");
}
});
thread1.start();
waitForThreadToStart.acquire(); // Wait for thread to start
thread1.join(); // Now do the join.
for (int i = 0; i < 10; i++) {
System.out.println(i);
}
}
}
Upvotes: 1
Reputation: 30111
By calling Thread.join()
The current thread waits for the thread you are calling join()
.
In you case you are waiting for thread1
to complete before it even started.
If you want thread1
to wait for the numbers to complete printing, you can use a CountDownLatch
docs:
public class Main {
public static final CountDownLatch startSignal = new CountDownLatch(1);
public static void main(String[] args)throws Exception {
Thread thread1=new Thread(new Runnable()
{
public void run()
{
try {
startSignal.await();
System.out.println("Thread1");
} catch (InterruptedException ex) {}
}
});
thread1.start();
for (int i = 0; i < 1000; i++) {
System.out.println(i);
}
startSignal.countDown();
thread1.join();
}
}
Upvotes: 1
Reputation: 21371
Despite the fact that you should call thread1.start()
before thread1.join()
you actually don't know when the thread will be executed. It can happen while printing your i
, it could happen before or it could happen after. Depends on the thread scheduling mechanism of your OS. Your correct code should look like this:
public class Main {
public static void main(String[] args)throws Exception {
Thread thread1=new Thread(new Runnable()
{
public void run()
{
System.out.println("Thread1");
}
});
// start the thread
thread1.start();
// print the numbers... meanwhile your thread *could* get executed
for (int i = 0; i < 1000; i++) {
System.out.println(i);
}
// wait for thread1 to finish
thread1.join();
}
}
Upvotes: 1
Reputation: 240900
thread1.join();
thread1.start()
make it
thread1.start()
thread1.join();
It will start a thread from main thread by thread1.start()
and main thread will continue to execute at the very next line it will see thread1.join();
which will pause main thread's execution until thread1 finishes. so your work will get done
Upvotes: 4