├── README.md ├── src ├── main │ ├── resources │ │ ├── application.properties │ │ └── application.yml │ └── java │ │ └── com │ │ └── javatechie │ │ └── executor │ │ └── api │ │ ├── repository │ │ └── UserRepository.java │ │ ├── SpringbootMultithreadingExampleApplication.java │ │ ├── entity │ │ └── User.java │ │ ├── config │ │ └── AsyncConfig.java │ │ ├── controller │ │ └── UserController.java │ │ └── service │ │ └── UserService.java └── test │ └── java │ └── com │ └── javatechie │ └── executor │ └── api │ └── SpringbootMultithreadingExampleApplicationTests.java └── pom.xml /README.md: -------------------------------------------------------------------------------- 1 | # springboot-multithreading-example -------------------------------------------------------------------------------- /src/main/resources/application.properties: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /src/main/resources/application.yml: -------------------------------------------------------------------------------- 1 | spring: 2 | h2: 3 | console: 4 | enabled: true 5 | 6 | server: 7 | port: 9191 -------------------------------------------------------------------------------- /src/main/java/com/javatechie/executor/api/repository/UserRepository.java: -------------------------------------------------------------------------------- 1 | package com.javatechie.executor.api.repository; 2 | 3 | import com.javatechie.executor.api.entity.User; 4 | import org.springframework.data.jpa.repository.JpaRepository; 5 | 6 | public interface UserRepository extends JpaRepository { 7 | } 8 | -------------------------------------------------------------------------------- /src/test/java/com/javatechie/executor/api/SpringbootMultithreadingExampleApplicationTests.java: -------------------------------------------------------------------------------- 1 | package com.javatechie.executor.api; 2 | 3 | import org.junit.jupiter.api.Test; 4 | import org.springframework.boot.test.context.SpringBootTest; 5 | 6 | @SpringBootTest 7 | class SpringbootMultithreadingExampleApplicationTests { 8 | 9 | @Test 10 | void contextLoads() { 11 | } 12 | 13 | } 14 | -------------------------------------------------------------------------------- /src/main/java/com/javatechie/executor/api/SpringbootMultithreadingExampleApplication.java: -------------------------------------------------------------------------------- 1 | package com.javatechie.executor.api; 2 | 3 | import org.springframework.boot.SpringApplication; 4 | import org.springframework.boot.autoconfigure.SpringBootApplication; 5 | 6 | @SpringBootApplication 7 | public class SpringbootMultithreadingExampleApplication { 8 | 9 | public static void main(String[] args) { 10 | SpringApplication.run(SpringbootMultithreadingExampleApplication.class, args); 11 | } 12 | 13 | } 14 | -------------------------------------------------------------------------------- /src/main/java/com/javatechie/executor/api/entity/User.java: -------------------------------------------------------------------------------- 1 | package com.javatechie.executor.api.entity; 2 | 3 | import lombok.AllArgsConstructor; 4 | import lombok.Data; 5 | import lombok.NoArgsConstructor; 6 | 7 | import javax.persistence.Entity; 8 | import javax.persistence.GeneratedValue; 9 | import javax.persistence.Id; 10 | import javax.persistence.Table; 11 | 12 | @Data 13 | @Entity 14 | @Table(name = "USER_TBL") 15 | @AllArgsConstructor 16 | @NoArgsConstructor 17 | public class User { 18 | @Id 19 | @GeneratedValue 20 | private int id; 21 | private String name; 22 | private String email; 23 | private String gender; 24 | } 25 | -------------------------------------------------------------------------------- /src/main/java/com/javatechie/executor/api/config/AsyncConfig.java: -------------------------------------------------------------------------------- 1 | package com.javatechie.executor.api.config; 2 | 3 | import org.springframework.context.annotation.Bean; 4 | import org.springframework.context.annotation.Configuration; 5 | import org.springframework.scheduling.annotation.EnableAsync; 6 | import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor; 7 | 8 | import java.util.concurrent.Executor; 9 | 10 | @Configuration 11 | @EnableAsync 12 | public class AsyncConfig { 13 | 14 | @Bean(name ="taskExecutor") 15 | public Executor taskExecutor(){ 16 | ThreadPoolTaskExecutor executor=new ThreadPoolTaskExecutor(); 17 | executor.setCorePoolSize(2); 18 | executor.setMaxPoolSize(2); 19 | executor.setQueueCapacity(100); 20 | executor.setThreadNamePrefix("userThread-"); 21 | executor.initialize(); 22 | return executor; 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 4.0.0 5 | 6 | org.springframework.boot 7 | spring-boot-starter-parent 8 | 2.2.1.RELEASE 9 | 10 | 11 | com.javatechie 12 | springboot-multithreading-example 13 | 0.0.1-SNAPSHOT 14 | springboot-multithreading-example 15 | Demo project for Spring Boot 16 | 17 | 18 | 1.8 19 | 20 | 21 | 22 | 23 | org.springframework.boot 24 | spring-boot-starter-data-jpa 25 | 26 | 27 | org.springframework.boot 28 | spring-boot-starter-web 29 | 30 | 31 | 32 | com.h2database 33 | h2 34 | runtime 35 | 36 | 37 | org.projectlombok 38 | lombok 39 | true 40 | 41 | 42 | org.springframework.boot 43 | spring-boot-starter-test 44 | test 45 | 46 | 47 | org.junit.vintage 48 | junit-vintage-engine 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | org.springframework.boot 58 | spring-boot-maven-plugin 59 | 60 | 61 | 62 | 63 | 64 | -------------------------------------------------------------------------------- /src/main/java/com/javatechie/executor/api/controller/UserController.java: -------------------------------------------------------------------------------- 1 | package com.javatechie.executor.api.controller; 2 | 3 | import com.javatechie.executor.api.entity.User; 4 | import com.javatechie.executor.api.service.UserService; 5 | import org.springframework.beans.factory.annotation.Autowired; 6 | import org.springframework.http.HttpStatus; 7 | import org.springframework.http.MediaType; 8 | import org.springframework.http.ResponseEntity; 9 | import org.springframework.web.bind.annotation.GetMapping; 10 | import org.springframework.web.bind.annotation.PostMapping; 11 | import org.springframework.web.bind.annotation.RequestParam; 12 | import org.springframework.web.bind.annotation.RestController; 13 | import org.springframework.web.multipart.MultipartFile; 14 | 15 | import java.util.List; 16 | import java.util.concurrent.CompletableFuture; 17 | 18 | @RestController 19 | public class UserController { 20 | @Autowired 21 | private UserService service; 22 | 23 | @PostMapping(value = "/users", consumes = {MediaType.MULTIPART_FORM_DATA_VALUE}, produces = "application/json") 24 | public ResponseEntity saveUsers(@RequestParam(value = "files") MultipartFile[] files) throws Exception { 25 | for (MultipartFile file : files) { 26 | service.saveUsers(file); 27 | } 28 | return ResponseEntity.status(HttpStatus.CREATED).build(); 29 | } 30 | 31 | @GetMapping(value = "/users", produces = "application/json") 32 | public CompletableFuture findAllUsers() { 33 | return service.findAllUsers().thenApply(ResponseEntity::ok); 34 | } 35 | 36 | 37 | @GetMapping(value = "/getUsersByThread", produces = "application/json") 38 | public ResponseEntity getUsers(){ 39 | CompletableFuture> users1=service.findAllUsers(); 40 | CompletableFuture> users2=service.findAllUsers(); 41 | CompletableFuture> users3=service.findAllUsers(); 42 | CompletableFuture.allOf(users1,users2,users3).join(); 43 | return ResponseEntity.status(HttpStatus.OK).build(); 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /src/main/java/com/javatechie/executor/api/service/UserService.java: -------------------------------------------------------------------------------- 1 | package com.javatechie.executor.api.service; 2 | 3 | import com.javatechie.executor.api.entity.User; 4 | import com.javatechie.executor.api.repository.UserRepository; 5 | import org.slf4j.Logger; 6 | import org.slf4j.LoggerFactory; 7 | import org.springframework.beans.factory.annotation.Autowired; 8 | import org.springframework.scheduling.annotation.Async; 9 | import org.springframework.stereotype.Service; 10 | import org.springframework.web.multipart.MultipartFile; 11 | 12 | import java.io.BufferedReader; 13 | import java.io.IOException; 14 | import java.io.InputStreamReader; 15 | import java.util.ArrayList; 16 | import java.util.List; 17 | import java.util.concurrent.CompletableFuture; 18 | 19 | @Service 20 | public class UserService { 21 | 22 | @Autowired 23 | private UserRepository repository; 24 | 25 | Object target; 26 | Logger logger = LoggerFactory.getLogger(UserService.class); 27 | 28 | @Async 29 | public CompletableFuture> saveUsers(MultipartFile file) throws Exception { 30 | long start = System.currentTimeMillis(); 31 | List users = parseCSVFile(file); 32 | logger.info("saving list of users of size {}", users.size(), "" + Thread.currentThread().getName()); 33 | users = repository.saveAll(users); 34 | long end = System.currentTimeMillis(); 35 | logger.info("Total time {}", (end - start)); 36 | return CompletableFuture.completedFuture(users); 37 | } 38 | @Async 39 | public CompletableFuture> findAllUsers(){ 40 | logger.info("get list of user by "+Thread.currentThread().getName()); 41 | List users=repository.findAll(); 42 | return CompletableFuture.completedFuture(users); 43 | } 44 | 45 | private List parseCSVFile(final MultipartFile file) throws Exception { 46 | final List users = new ArrayList<>(); 47 | try { 48 | try (final BufferedReader br = new BufferedReader(new InputStreamReader(file.getInputStream()))) { 49 | String line; 50 | while ((line = br.readLine()) != null) { 51 | final String[] data = line.split(","); 52 | final User user = new User(); 53 | user.setName(data[0]); 54 | user.setEmail(data[1]); 55 | user.setGender(data[2]); 56 | users.add(user); 57 | } 58 | return users; 59 | } 60 | } catch (final IOException e) { 61 | logger.error("Failed to parse CSV file {}", e); 62 | throw new Exception("Failed to parse CSV file {}", e); 63 | } 64 | } 65 | } 66 | --------------------------------------------------------------------------------