Sal B
Sal B

Reputation: 93

Waiting for a thread to finish in Spring application

I am working with a Java Spring application and I've implemented a thread that starts after application start up as follows:

@Component
public class AppStartup implements ApplicationListener<ApplicationReadyEvent> {
    @Autowired
    private SomeService service;

    @Override
    public void onApplicationEvent(final ApplicationReadyEvent event) {
        service.executeAsyn();
    }
}

@Service
public class SomeService {
    private TaskExecutor taskExecutor;
    private ApplicationContext applicationContext;

    @Autowired
    private SomeService(TaskExecutor taskExecutor, ApplicationContext applicationContext) {
        this.taskExecutor = taskExecutor;
        this.applicationContext = applicationContext;
    }

    public void executeAsyn() {
        ResellerSyncThread myThread = applicationContext.getBean(MyThread.class);
        taskExecutor.execute(myThread);
    }

    public void methodToExecute() {
        //do something
    }
}

@Component
@Scope("prototype")
public class MyThread implements Runnable {
    @Autowired
    SomeService service;

    @Override
    public void run() {
        service.methodToExecute();
    }
}

Essentially, my goal is to start a thread after application startup whose job is to run one method (methodToexecute) and terminate. This approach seems to work and is simpler that ThreadPool since I only want one task.

My question is how can I wait for the thread to start and then finish from my main thread to do some validation.

from main thread

public class SomeTest {
    @Test
    public void test() {
        //wait for thread to start

        //do something

        //wait for thread to finish

        //do something else

    }
}

Please feel free to comment on my approach to implement the thread as well. If you have a suggestion on how to make it better, potential problems with this approach, etc.

Upvotes: 0

Views: 5156

Answers (3)

SRm
SRm

Reputation: 49

Since you need the 2 methods to be executed in sequence you can used @DependsOn annotation in Spring. You can declare them as beans and Spring guarantees if a bean A has dependency of B, then B will be initialized first. So bean "firstMethod" 's init method "initialize" must do what you need

  @Component
    public class Example{

        @Bean(initMethod = "init")
        @DependsOn("firstMethod")
        public void doSomethingElse() {
           //do something. Check flag if needed
        }

        @Bean(name = "firstMethod", initMethod = "initialize")
        public void doSomething() {
            //do something. 
        }

        //more methods
    }

Upvotes: 0

Daniel Facciabene
Daniel Facciabene

Reputation: 101

This might be an a approximation of what you need: adding a flag to the Thread class then checking for it during main.

@Component
@Scope("prototype")
public class MyThread implements Runnable {
    @Autowired
    SomeService service;

    private static boolean done = false;

    public static boolean isDone() {
        return done;
    }

    @Override
    public void run() {
        service.methodToExecute();
        done = true;
    }
}

And in the main method:

public class SomeTest {
    @Test
    public void test() {
        //wait for thread to start

        //do something

        while(!MyThread.isDone())
             Thread.sleep(200); // or some other number you adjust

        //do something else

    }
}

*Note that this only works if you run executeAsyn() just once, you should have to do some modifications otherwise.

This solution is kind of dirty and you can probably find cleaner ways of doing what you want with some more reasearch.

Upvotes: 2

Christian B
Christian B

Reputation: 102

here are some options: 1. implement callbacks to trigger before/after the start/end of the thread 2. create a separate thread that is reading a static flag and have the other thread set that flag

However, it seems unclear to me why this would ever be used?

Upvotes: 0

Related Questions