Reputation: 71
I am very new to Spring and I am trying to call two methods from two separate classes a number of times, and I want each invocation to spin a new thread so they run concurrently. This is the code I have:
the main class:
@SpringBootApplication
@EnableOAuth2Client
@EnableAsync
public class MainApplication {
public static void main(String[] args) {
SpringApplication.run(MainApplication.class, args);
}
}
class SomeOtherClass {
for (int i = 0; i < 100; i++) {
Class1 class1 = new Class1();
class1.method1(//its arguments);
}
// doing other things
// ...
// method 2 will use the side effects of method 1, so ideally this next
// for loop should start only after the previous one is over
for (int i = 0; i < 50; i++) {
Class2 class2 = new Class2();
class2.method2(//its arguments);
}
}
public Class1 {
@Async("threadPoolTaskExecutor")
public void method1() throws Exception {
LOGGER.info("Running this in {}", Thread.currentThread().getName());
}
}
public Class2 {
@Async("threadPoolTaskExecutor")
public void method2() throws Exception {
LOGGER.info("Running this in {}", Thread.currentThread().getName());
}
}
@Configuration
@EnableAsync
public class ThreadConfig {
@Bean("threadPoolTaskExecutor")
public TaskExecutor threadPoolTaskExecutor() {
ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
executor.setCorePoolSize(100);
executor.setMaxPoolSize(100);
executor.initialize();
return executor;
}
}
The problem is when I run the application I only see one thread name printing, which means it's not running in a multithreaded way. Looking at the logs, I can also see the calls are being made sequentially. Having done multithreading using standard Java (Runnable), I know the multithreaded version should finish much faster. Since I am very new to Spring, I do not understand what I am doing wrong.
I have redacted the method names and logic, but the annotations and class structures are exactly thee same, so if you see any problem with that please point that out.
Upvotes: 1
Views: 1686
Reputation: 530
To get method1
and method2
work asynchronously you have to let Spring manage instances of the Class1 and Class2. Replace Class1 class1 = new Class1();
with the dependency injection.
@Service
public Class1 {
...
@Service
class SomeOtherClass {
@Autowired
Class1 class1;
//...
// your loops
EDIT:
If you need to perform second loop only after completion of all async executions in the first loop then you can use Future
class:
@Async(...)
public Future<Object> method1() {
...
return null;
}
List<Future<Object>> futures = new ArrayList<>();
for (int i = 0; i < 1000; i++) {
futures.add(class1.method1(/*its arguments*/));
}
futures.forEach(f -> {
try {
f.get();
} catch (ExecutionException | InterruptedException e) {
e.printStackTrace();
}
});
// all of invocations of method1 are finished
Upvotes: 1