Thread scheduler is responsible for scheduling of threads. So every time you run the program, there is no guarantee to the order of execution of threads. Suppose you have a thread object named threadOne and if join() is called on threadOne like this:
then all currently executing threads will be paused until thread1 has finished its execution or terminates.
Consider the following piece of code:
class RunnableSample implements Runnable {
private Thread t;
private String threadName;
public RunnableSample(String name) {
this.threadName = name;
}
public void run() {
try {
for(int i = 4; i >= 1; i--) {
System.out.println(Thread.currentThread().getName() + ", " + i);
Thread.sleep(500);
}
} catch (InterruptedException e) {
System.out.println(threadName + " interrupted");
}
}
public void start() {
if(t == null)
t = new Thread(this, threadName);
t.start();
try {
t.join();
} catch(Exception e) {
System.out.println(e);
}
}
}
public class RunnableDemo {
public static void main(String[] args) {
RunnableSample r1 = new RunnableSample("threadOne");
r1.start();
RunnableSample r2 = new RunnableSample("threadTwo");
r2.start();
RunnableSample r3 = new RunnableSample("threadThree");
r3.start();
}
}
The output of the above program will be:
threadOne, 4
threadOne, 3
threadOne, 2
threadOne, 1
threadTwo, 4
threadTwo, 3
threadTwo, 2
threadTwo, 1
threadThree, 4
threadThree, 3
threadThree, 2
threadThree, 1
Since join() is called on threadOne first, threadTwo and threadThree will be paused until threadOne terminates. (NOTE that threadOne, threadTwo and ThreadThree all have started). Now the threads are executing in a specific order. If join() is not called on a thread in our example, then there will be no order of execution of threads.
public void start() {
if(t == null)
t = new Thread(this, threadName);
t.start();
}
Its output will be:
threadOne, 4
threadThree, 4
threadTwo, 4
threadTwo, 3
threadThree, 3
threadOne, 3
threadOne, 2
threadThree, 2
threadTwo, 2
threadOne, 1
threadThree, 1
threadTwo, 1
Coming to synchronization, which is useful if you want to control the access of multiple threads on any shared resource. If you want to restrict only one thread to access shared resources then synchronization is the best way to do it.