Spring Boot Asynchronous Controller
2 min readNov 6, 2019
- Create Async Thread Pool
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.annotation.EnableAsync;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
import java.util.concurrent.Executor;
@Configuration
@EnableAsync
public class MainConfiguration {
@Bean(name = "asyncExecutor")
public Executor asyncExecutor()
{
ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
executor.setCorePoolSize(5);
executor.setMaxPoolSize(5);
executor.setQueueCapacity(100);
executor.setThreadNamePrefix("AsynchThreadNo-");
executor.initialize();
return executor;
}
}
สร้าง Data Model สำหรับ Customer
public class Customer {
private String name;
private Integer age;
public Customer(String name, Integer age) {
this.name = name;
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Integer getAge() {
return age;
}
public void setAge(Integer age) {
this.age = age;
}
@Override
public String toString() {
return "Customer{" +
"name='" + name + '\'' +
", age='" + age + '\'' +
'}';
}
}
MySevice สำหรับ get ข้อมูล Customer
import com.ringzero.research.model.Customer;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;
import javax.annotation.PostConstruct;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.CompletableFuture;
@Service
public class MyService {
private List<Customer> customerList = new ArrayList<>();
@PostConstruct
public void initialize() {
for (int i=1; i <= 1000; i++) {
customerList.add(new Customer("name-" + i, i));
}
}
@Async("asyncExecutor")
public CompletableFuture<List<Customer>> getCustomer1() throws InterruptedException
{
Thread.sleep(1000L); //Intentional delay
return CompletableFuture.completedFuture(customerList.subList(1, 500));
}
@Async("asyncExecutor")
public CompletableFuture<List<Customer>> getCustomer2() throws InterruptedException
{
Thread.sleep(2000L); //Intentional delay
return CompletableFuture.completedFuture(customerList.subList(300, 700));
}
@Async("asyncExecutor")
public CompletableFuture<List<Customer>> getCustomer3() throws InterruptedException
{
Thread.sleep(3000L); //Intentional delay
return CompletableFuture.completedFuture(customerList.subList(600, 900));
}
}
Controller
import com.ringzero.research.model.Customer;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;
import java.util.List;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutionException;
import static org.apache.kafka.common.requests.DeleteAclsResponse.log;
@RestController
public class MyController {
@Autowired
private MyService service;
@RequestMapping(value = "/getAsynchData", method = RequestMethod.GET)
public String getAsynchData() throws InterruptedException, ExecutionException
{
final long startTime = System.currentTimeMillis();
CompletableFuture<List<Customer>> customer1 = service.getCustomer1();
CompletableFuture<List<Customer>> customer2 = service.getCustomer2();
CompletableFuture<List<Customer>> customer3 = service.getCustomer3();
// Wait until they are all done
CompletableFuture.allOf(customer1, customer2, customer3).join();
log.info("customer1--> " + customer1.get());
log.info("customer2--> " + customer2.get());
log.info("customer3--> " + customer3.get());
final long duration = (System.currentTimeMillis() - startTime) / 1000;
return "" + duration + " secs";
}
}
ถ้าเราไม่ทำ Asynch Controller เวลาการทำงานจะประมาณ 6 sec
แต่ถอทำ Asynch แล้วจะเหลือประมาณ 3 sec คือที่ sleep นานที่สุด