Here is a scenario, when the output I am expecting from below code is
First Function
Second Function
Main Execution Completed!
But the problem here is the run method that prints "Second Function" is never getting the value of volatile flag to true to print "Second Function" and call countDown on countdownlatch object. Hence the countdownlatch.await() keeps waiting without any outcome. Is there any other approach to execute the respective run methods in a particular sequence? I understand this defeats the purpose of asynchronous programming in java, but if at all its possible kindly let me know.
public class Application {
private static CountDownLatch countDownLatch = new CountDownLatch(2);
public static void executeAndWait(List<Runnable> runnables) {
runnables.forEach(r -> new Thread(r).start());
}
public static void main(String[] args) throws InterruptedException {
List<Runnable> runnables = Arrays.asList(() -> {
try {
while(flag) {
Thread.sleep(100);
System.out.println("Second Function");
countDownLatch.countDown();
break;
}
} catch(Exception e) {}
}, () -> {
try {
Thread.sleep(100);
System.out.println("First Function");
flag = true;
countDownLatch.countDown();
} catch(Exception e) {}
});
executeAndWait(runnables);
countDownLatch.await();
System.out.println("Main Execution Completed!");
}
}
Core problem here is that when the second thread reaches the condition guarding the while
loop:
...
while(flag) {
...
flag
may be either true
of false
. If flag
is false
then the whole loop is skipped, and the execution of that thread terminates.
What we actually want is an endless loop, with a condition that
when flag
is true
.
Hence, we can rewrite the Runnable
:
() -> {
try {
while (true) { // keep looping...
if (flag) { // ... until flag is set
System.out.println("Second Function");
countDownLatch.countDown();
break;
}
Thread.sleep(100);
}
} catch (Exception e) {
}
}
A remark on the code: We can and should move the try { ... } catch (...) { ... }
as close to the Thread.sleep(...)
as possible. Hence, I propose the following structual change:
() -> {
while (true) {
try {
Thread.sleep(100);
} catch (Exception e) {
}
if (flag) {
countDownLatch.countDown();
System.out.println("Second Function");
break;
}
}
}