Reputation: 93
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
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
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
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