Search code examples
javamultithreadingcucumbercucumber-jvmcucumber-java

Java program exits before thread has finished. How do I make Cucumber-JVM wait for the thread to exit?


I am trying to create a new thread in my Cucumber-JVM program, when I reach a certain BDD step.

Then, one thread should be doing something, while the original main thread continues running through the cucumber steps.

The program shouldn't exit until all threads have finished.

The problem I'm running into, is the main program exits before the thread is finished.

Here is what's happening:


Output / Problem

  • Main program is RunApiTest
  • The thread class is ThreadedSteps.

Here is what happens when I run the program:

  1. RunApiTest starts going through all steps
  2. RunApiTest gets to "I should receive an email within 5 minutes"
  3. RunApiTest now creates a thread ThreadedSteps, which should sleep for 5 minutes.
  4. ThreadedSteps starts to sleep for 5 minutes
  5. While ThreadedSteps is sleeping, RunApiTest continues running the rest of the Cucumber BDD steps
  6. RunApiTest finishes and exits, without waiting for ThreadedSteps to finish!

How do I make my program WAIT until my thread is done?


Here is my code

Main Cucumber Class: RunApiTest

@RunWith(Cucumber.class)
@CucumberOptions(plugin={"pretty"}, glue={"mycompany"}, features={"features/"})
public class RunApiTest {
}

Cucumber Step to Trigger Thread: email_bdd

@Then("^I should receive an email within (\\d+) minutes$")
public void email_bdd(int arg1) throws Throwable {
     Thread thread = new Thread(new ThreadedSteps(arg1));
     thread.start();
}

Thread Class: ThreadedSteps

public class ThreadedSteps implements Runnable {

    private int seconds_g;

    public ThreadedSteps(Integer seconds) {
        this.seconds_g = seconds;
    }

    @Override
    public void run() {
        Boolean result = waitForSecsUntilGmail(this.seconds_g);
    }

    public void pauseOneMin()
    {
        Thread.sleep(60000);
    }

    public Boolean waitForSecsUntilGmail(Integer seconds)
    {
        long milliseconds = seconds*1000;
        long now = Instant.now().toEpochMilli();
        long end = now+milliseconds;

        while(now<end)
        {
            //do other stuff, too
            pauseOneMin();
        }
        return true;
    }
}

Attempt #1

I tried adding join() to my thread, but that halted my main program's execution until the thread was done, then continued executing the rest of the program. This is not what I want, I want the thread to sleep while the main program continues executing.

@Then("^I should receive an email within (\\d+) minutes$")
public void email_bdd(int arg1) throws Throwable {
     Thread thread = new Thread(new ThreadedSteps(arg1));
     thread.start();
     thread.join();
}

Solution

  • thread.join() does exactly that -- it requires the program to halt execution until that thread has terminated. If you want your main thread to continue doing work, you need to put your join() at the bottom of the code. That way, the main thread can complete all of its tasks and then wait for your thread.