There are thread T1, T2 and T3, how can we ensure that thread T2 run after T1 and thread T3 run after T2?
This question was asked in my interview. I didn't answer. Please explain in detail.
There are thread T1, T2 and T3, how can we ensure that thread T2 run after T1 and thread T3 run after T2?
This question was asked in my interview. I didn't answer. Please explain in detail.
There are thread T1, T2 and T3, how can we ensure that thread T2 run after T1 and thread T3 run after T2? OR There are three threads T1, T2 and T3? How do you ensure sequence T1, T2, T3 in Java? The question basically is T3 should finish first , T2 second and T1 last. We can use use join() method of thread class. To ensure three threads execute you need to start the last one first e.g. T3 and then call join methods in reverse order e.g. T3 calls T2.join, and T2 calls T1.join. In this way, T1 will finish first and T3 will finish last.
public class Test1 {
public static void main(String[] args) {
final Thread t1 = new Thread(new Runnable() {
public void run() {
System.out.println("start 1");
System.out.println("end 1");
}//run
});
final Thread t2 = new Thread(new Runnable() {
public void run() {
System.out.println(" start 2 ");
try {
t1.join(2000);
} catch (Exception e) {
e.getStackTrace();
}
System.out.println(" end 2");
}
}) ;
final Thread t3 = new Thread( new Runnable() {
public void run() {
System.out.println(" start 3 ");
try {
t2.join(4000);
}catch(Exception e) {
e.getStackTrace();
}
System.out.println(" end 3 ");
}
});
// we are reversing the order of the start() method
t3.start();
t2.start();
t1.start();
}
}
From the output, You can see that threads have started in different order as you don't know which thread will get CPU. Its the decision of the Thread Scheduler, so we cannot do anything. But, you can see that threads are finished in correct order i.e. T1 then T2 and then T3.
There is another way of doing it. The pseudo code is :
t1.start();
t1.join(); // signals t2 to wait
if( !t1.isAlive()) {
t2.start();// if t1 is finished then t2 will start
}
t2.join();//signals t3 to wait
if (!t2.isAlive()) {
t3.start();
}
Let's take a full program:
public class Tic implements Runnable{
public void run() {
try {
for (int i = 0; i < 2; i++) {
System.out.println("tic");
}
} catch (Exception e) {
// TODO: handle exception
e.getStackTrace();
}
}
}
public class Tac implements Runnable{
public void run() {
try {
for (int i = 0; i < 2; i++) {
System.out.println("tac");
}
} catch (Exception e) {
// TODO: handle exception
e.getStackTrace();
}
}
}
public class Toe implements Runnable{
public void run() {
try {
for (int i = 0; i < 2; i++) {
System.out.println("toe");
}
} catch (Exception e) {
// TODO: handle exception
e.getStackTrace();
}
}
}
public class RunThreads1 {
public static void main(String[] args) {
try {
Tic tic = new Tic();
Tac tac = new Tac();
Toe toe = new Toe();
Thread t1 = new Thread(tic);
Thread t2 = new Thread(tac);
Thread t3 = new Thread(toe);
t1.start();
t1.join(); // signals t2 to wait
if( !t1.isAlive()) {
t2.start();// if t1 is finished then t2 will start
}
t2.join();//signals t3 to wait
if (!t2.isAlive()) {
t3.start();
}
}catch(InterruptedException e) {
e.printStackTrace();
}
}
}
The output is : tic tic tac tac toe toe
how can we ensure that thread T2 run after T1 and thread T3 run after T2?
NOTE: Assuming that it is not about scheduling the threads in the required order
We could use the Condition Interface.
We'll need two conditions bound to a single Lock: condition1 to coordinate T1 and T2, condition2 to coordinate T2 and T3.
Pass condition1 to T1 and T2, condition2 to T2 and T3.
So, we would have T2 await on condition1 in it's run method, which will be signalled by T1 (from T1's run method, after T1 starts/finishes its task).
Similarly have T3 await on condition2 in it's run method, which will be signalled by T2 (from T2's run method, after it starts/finishes it's task).
package io.hariom.threading;
//You have three threads T1, T2, and T3, How do you ensure that they finish in order T1, T2, T3 ?
public class ThreadTest1 {
public static void main(String[] args) {
Thread thread1 = new Thread(new MyRunnable(null));
Thread thread2 = new Thread(new MyRunnable(thread1));
Thread thread3 = new Thread(new MyRunnable(thread2));
thread1.start();
thread2.start();
thread3.start();
}
}
class MyRunnable implements Runnable { Thread t;
MyRunnable(Thread t) {
this.t = t;
}
@Override
public void run() {
if (t != null) {
try {
t.join();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
System.out.println(Thread.currentThread().getName() + " starts");
try {
Thread.sleep(10);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName() + " ends");
}
}
Here is my approach to the problem using CountDownLatch for signalling .
T1 thread after doing its job signal to T2 and T2 to T3.
public class T1T2T3 {
public static void main(String[] args) {
CountDownLatch c1 = new CountDownLatch(1);
CountDownLatch c2 = new CountDownLatch(1);
Thread T1 = new Thread(new Runnable() {
@Override
public void run() {
System.out.println("T1");
c1.countDown();
}
});
Thread T2 = new Thread(new Runnable() {
@Override
public void run() {
//should listen to something from T1
try {
c1.await();
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("T2");
c2.countDown();
}
});
Thread T3 = new Thread(new Runnable() {
@Override
public void run() {
try {
c2.await();
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("T3");
}
});
T1.start();
T3.start();
T2.start();
}
}