Let's say we have this scenario:
class Stack{
public void main{
ChildThread1 t1 = new ChildThread1;
ChildThread1 t2 = new ChildThread1;
ChildThread1 t3 = new ChildThread1;
//then we make some ChildThread2 objects and some ChildThread3 objects
ChildThread2 s1 = new ChildThread2;
//...
ChildThread3 v1 = new ChildThread3;
//...
//now we let all threads start in mix order
t1.start();
v1.start();
//...
SOP("All threads are ready");
//then we let them run with join()
t1.join();
t2.join();
t3.join();
s1.join();
//...
v1.join();
//...
Each type of thread prints its own unique statement when it is running.
I noticed that every time I execute the program, the output is always different. For example, a statement from ChilThread1 t1 will print in the middle of output instead of beginning (since t1 starts first) or the statement "all threads are ready" will pop in middle of thread execution (Example: ChildThread2 is 'all threads are ready' running )
So I tried to find an answer and I found this site: http://www.avajava.com/tutorials/lessons/how-do-i-use-threads-join-method.html The site basically says there's no guarantee order of execution when you use start()
So am I right to assume that this weird order of prints is because start() does not guarantee order of execution? Will this reason also apply to 'all threads are ready' problem?
Because threads run at the same time as other parts of the program, there is no way to know in which order the code will run.
You cannot tell the thread scheduler which order to execute threads in. If you need to ensure that a certain piece of code which is running on thread A must run before another piece of code running on thread B, you must enforce that order using locks or wait() / notify() .
When multiple threads are ready to execute, the JVM selects and executes the Runnable thread that has the highest priority. If this thread stops or becomes not runnable, the lower-priority threads will execute. In case two threads have the same priority, the JVM will execute them in FIFO order.
Threads have some priority. Because of that thread scheduler assign processor to thread. It is possible to have same priority to threads.
The whole point of threads is that they can be executed concurrently. If you want to ensure specific order in which things are done, you either have to move away from using threads, or use explicit synchronization.
So am I right to assume that this weird order of prints is because start() does not guarantee order of execution?
That's right. When you start
a thread, there's basically a race condition between the main thread and the newly created thread. This means that nothing can be said about the relative order in which things happen between the two threads. If you want to ensure specific ordering, use synchronization.
When you start a thread, the started thread runs in parallel of all the already running threads. The thread scheduler dispatches the various threads on the available processors, and each thread gets some processor time, each in his turn. But the processor, the order and the time assigned to each thread is up to the OS thread scheduler, and you have absolutely no guarantee.
Easy way to maintain ordering in Thread Execution is to use Semaphore
public class Semaphore {
int value;
public Semaphore(int intialValue) {
this.value = intialValue;
}
public synchronized void p() {
while (value <= 0) {
try {
this.wait();
} catch (InterruptedException e) {
}
}
value = value - 1;
}
public synchronized void v() {
value = value + 1;
this.notify();
}
}
public class ThreadSync {
static Semaphore semaphore = new Semaphore(0);
public static void main(String[] args) {
// t1 should be executed before t2
Thread t1 = new Thread(new Runnable() {
@Override
public void run() {
semaphore.p();
System.out.println("executing " + Thread.currentThread().getName());
}
});
Thread t2 = new Thread(new Runnable() {
@Override
public void run() {
System.out.println("executing " + Thread.currentThread().getName());
semaphore.v();
}
});
t1.setName("Thread 1");
t2.setName("Thread 2");
t2.start();
t1.start();
}
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With