Today we will look a little bit at Java, for example, an interview question you are asked is as follows: the request requires three threads to execute sequentially, and what implementations are there to achieve it?
The problem will be that we have three streams: Stream 1, Stream 2, and Stream 3, the requirement is that stream 1 will be processed first, then stream 2, and finally stream 3. We will have a few ways like after:
Use the Join method
import java.util.Objects;
public class ThreadMain {
public static void main(String[] args) {
var t1 = new Thread(new Work(null));
var t2 = new Thread(new Work(t1));
var t3 = new Thread(new Work(t2));
t1.start();
t2.start();
t3.start();
}
static class Work implements Runnable {
private Thread beforeThread;
public Work(Thread beforeThread) {
this.beforeThread = beforeThread;
}
@Override
public void run() {
if (Objects.nonNull(beforeThread)) {
try {
beforeThread.join();
System.out.println("Thread start : " + Thread.currentThread().getName());
} catch (InterruptedException e) {
e.printStackTrace();
}
} else {
System.out.println("Thread start : " + Thread.currentThread().getName());
}
}
}
}
Reading the above code, you can understand some of the logic, passing parameters into the initialization function of streams 1, 2, and 3. At this time, it stream 1will be processed first, stream 2join stream 1will be processed further, and join stream 3with stream 2will be processed last.
Start the application and see the results:
Use CountDown Latch
import java.util.concurrent.CountDownLatch;
public class CountDownLatchMain {
public static void main(String[] args) {
var countDownLatchOne = new CountDownLatch(0);
var countDownLatchTwo = new CountDownLatch(1);
var countDownLatchThree = new CountDownLatch(1);
var t1 = new Thread(new Work(countDownLatchOne, countDownLatchTwo));
var t2 = new Thread(new Work(countDownLatchTwo, countDownLatchThree));
var t3 = new Thread(new Work(countDownLatchThree, countDownLatchThree));
t1.start();
t2.start();
t3.start();
}
static class Work implements Runnable {
CountDownLatch cOne;
CountDownLatch cTwo;
public Work(CountDownLatch cOne, CountDownLatch cTwo) {
this.cOne = cOne;
this.cTwo = cTwo;
}
@Override
public void run() {
try {
cOne.await();
System.out.println("Thread using countdown latch start : " + Thread.currentThread().getName());
cTwo.countDown();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
Ok, now start the application and see the results, then go into detail about its execution:
In the function main(), three objects CountDownLatchare created with initial values of 0, 1, and 1.
- countDownLatchOneused to mark all threads as ready to start
- countDownLatchTwoused to start t2after t1having finished
- countDownLatchThreeused to start t3after t2having finished
Three objects are created with three corresponding Threadobjects passed in. WorkThen, three threads are started by calling the start().
In class Work, the implementation is shown as follows:
- Class Workis an implementation class Runnablewhose purpose is to perform some work executed in a separate thread.
- The class Workhas two input parameters, which are two objects of the class CountDownLatch, cOneand cTwo.
- run()In the class method Work, before starting to execute work, the thread will call the await()above method cOne, waiting until cOnethe countdown value is reduced to 0.
- The thread will then print a message to confirm that it has started doing its work. This is the marker for t1completing your work.
- Finally, the thread will call the countDown()above method cTwoto decrement the countdown value of cTwoto 0. Decreasing the countdown value of cTwowill mark the t2start of execution.
- The same process will continue for t2and t3in the correct order of entry. That is, t2it will wait until cTwothe countdown value is reduced to 0 by calling the await()above method cTwo, then print a confirmation message and finally reduce the countdown value to 0 by calling the above cThreemethod.countDown()cThree
- Similarly, t3it will wait until cThreethe countdown value is reduced to zero by calling the await()above method cThree, printing a confirmation message, and finally ending its execution.
Use ExecutorService
We can implement a single thread group using ExecutorService but only use a single thread because if we deploy multiple thread groups, the order of T1, T2, and T3 will not be guaranteed.
import java.util.concurrent.Executors;
public class ExecutorServiceMain {
public static void main(String[] args) {
Thread t1 = new Thread(() -> System.out.println("Thread Start : " + Thread.currentThread().getName() + " 1"));
Thread t2 = new Thread(() -> System.out.println("Thread Start : " + Thread.currentThread().getName() + " 2"));
Thread t3 = new Thread(() -> System.out.println("Thread Start : " + Thread.currentThread().getName() + " 3"));
var executor = Executors.newSingleThreadExecutor();
executor.submit(t1);
executor.submit(t2);
executor.submit(t3);
executor.shutdown();
}
}
Above are a few ways to solve the problem of processing the order of streams. Good luck with your studies.
Thanks, before you go:
👏 Please clap for the story and follow the author 👉
Please share your questions or insights in the comments section below.
Let’s connect on LinkedIn
Originally published at https://cafeincode.com on May 4, 2023.
Top comments (0)