Search code examples
multithreadingjava-8volatilecountdownlatch

How can we execute Java threads in a sequence?


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!");
    }
} 

Solution

  • 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

    • prints some text,
    • decreases the latch, and
    • breaks out of the loop

    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) {
      }
    }
    

    ideone.com demo


    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;
        }
      }
    }