save and get data at the same time

parents
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="CompilerConfiguration">
<annotationProcessing>
<profile default="true" name="Default" enabled="true" />
<profile name="Maven default annotation processors profile" enabled="true">
<sourceOutputDir name="target/generated-sources/annotations" />
<sourceTestOutputDir name="target/generated-test-sources/test-annotations" />
<outputRelativeToContentRoot value="true" />
<module name="springboot-multithreading-completable-future" />
</profile>
</annotationProcessing>
</component>
<component name="JavacSettings">
<option name="ADDITIONAL_OPTIONS_OVERRIDE">
<module name="springboot-multithreading-completable-future" options="-parameters" />
</option>
</component>
</project>
\ No newline at end of file
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="Encoding">
<file url="file://$PROJECT_DIR$/src/main/java" charset="UTF-8" />
</component>
</project>
\ No newline at end of file
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="RemoteRepositoriesConfiguration">
<remote-repository>
<option name="id" value="central" />
<option name="name" value="Central Repository" />
<option name="url" value="https://repo.maven.apache.org/maven2" />
</remote-repository>
<remote-repository>
<option name="id" value="central" />
<option name="name" value="Maven Central repository" />
<option name="url" value="https://repo1.maven.org/maven2" />
</remote-repository>
<remote-repository>
<option name="id" value="jboss.community" />
<option name="name" value="JBoss Community repository" />
<option name="url" value="https://repository.jboss.org/nexus/content/repositories/public/" />
</remote-repository>
</component>
</project>
\ No newline at end of file
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="ExternalStorageConfigurationManager" enabled="true" />
<component name="MavenProjectsManager">
<option name="originalFiles">
<list>
<option value="$PROJECT_DIR$/pom.xml" />
</list>
</option>
</component>
<component name="ProjectRootManager" version="2" languageLevel="JDK_18" default="true" project-jdk-name="openjdk-18" project-jdk-type="JavaSDK" />
</project>
\ No newline at end of file
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="VcsDirectoryMappings">
<mapping directory="$PROJECT_DIR$" vcs="Git" />
</component>
</project>
\ No newline at end of file
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="AutoImportSettings">
<option name="autoReloadType" value="SELECTIVE" />
</component>
<component name="ChangeListManager">
<list default="true" id="7d52f813-1e48-4468-b1b1-fd99c781225f" name="Changes" comment="" />
<option name="SHOW_DIALOG" value="false" />
<option name="HIGHLIGHT_CONFLICTS" value="true" />
<option name="HIGHLIGHT_NON_ACTIVE_CHANGELIST" value="false" />
<option name="LAST_RESOLUTION" value="IGNORE" />
</component>
<component name="MarkdownSettingsMigration">
<option name="stateVersion" value="1" />
</component>
<component name="MavenImportPreferences">
<option name="generalSettings">
<MavenGeneralSettings>
<option name="useMavenConfig" value="true" />
</MavenGeneralSettings>
</option>
</component>
<component name="ProjectId" id="2Bw1nxg1pxunG9ASy1LCXMBUIAm" />
<component name="ProjectViewState">
<option name="hideEmptyMiddlePackages" value="true" />
<option name="showLibraryContents" value="true" />
</component>
<component name="PropertiesComponent"><![CDATA[{
"keyToString": {
"RunOnceActivity.OpenProjectViewOnStart": "true",
"RunOnceActivity.ShowReadmeOnStart": "true",
"last_opened_file_path": "/Users/aqadeer/Desktop/springboot-multithreading-example-master",
"settings.editor.selected.configurable": "preferences.lookFeel"
}
}]]></component>
<component name="RunManager" selected="Application.com.example.SpringbootMultithreadingExampleApplication">
<configuration name="SpringbootMultithreadingExampleApplication" type="Application" factoryName="Application" temporary="true" nameIsGenerated="true">
<option name="MAIN_CLASS_NAME" value="com.javatechie.executor.api.SpringbootMultithreadingExampleApplication" />
<module name="springboot-multithreading-completable-future" />
<extension name="coverage">
<pattern>
<option name="PATTERN" value="com.javatechie.executor.api.*" />
<option name="ENABLED" value="true" />
</pattern>
</extension>
<method v="2">
<option name="Make" enabled="true" />
</method>
</configuration>
<configuration name="com.example.SpringbootMultithreadingExampleApplication" type="Application" factoryName="Application" temporary="true" nameIsGenerated="true">
<option name="MAIN_CLASS_NAME" value="com.example.SpringbootMultithreadingExampleApplication" />
<module name="springboot-multithreading-completable-future" />
<extension name="coverage">
<pattern>
<option name="PATTERN" value="com.example.*" />
<option name="ENABLED" value="true" />
</pattern>
</extension>
<method v="2">
<option name="Make" enabled="true" />
</method>
</configuration>
<configuration default="true" type="JetRunConfigurationType">
<module name="springboot-multithreading-completable-future" />
<method v="2">
<option name="Make" enabled="true" />
</method>
</configuration>
<configuration default="true" type="KotlinStandaloneScriptRunConfigurationType">
<module name="springboot-multithreading-completable-future" />
<option name="filePath" />
<method v="2">
<option name="Make" enabled="true" />
</method>
</configuration>
<recent_temporary>
<list>
<item itemvalue="Application.com.example.SpringbootMultithreadingExampleApplication" />
<item itemvalue="Application.SpringbootMultithreadingExampleApplication" />
</list>
</recent_temporary>
</component>
<component name="SpellCheckerSettings" RuntimeDictionaries="0" Folders="0" CustomDictionaries="0" DefaultDictionary="application-level" UseSingleDictionary="true" transferred="true" />
<component name="TaskManager">
<task active="true" id="Default" summary="Default task">
<changelist id="7d52f813-1e48-4468-b1b1-fd99c781225f" name="Changes" comment="" />
<created>1657802504077</created>
<option name="number" value="Default" />
<option name="presentableId" value="Default" />
<updated>1657802504077</updated>
</task>
<servers />
</component>
</project>
\ No newline at end of file
# springboot-multithreading-example
\ No newline at end of file
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.2.1.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>com.example</groupId>
<artifactId>springboot-multithreading-example</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>springboot-multithreading-example</name>
<description>Demo project for Spring Boot</description>
<properties>
<java.version>1.8</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
<exclusions>
<exclusion>
<groupId>org.junit.vintage</groupId>
<artifactId>junit-vintage-engine</artifactId>
</exclusion>
</exclusions>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
package com.example;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class SpringbootMultithreadingExampleApplication {
public static void main(String[] args) {
SpringApplication.run(SpringbootMultithreadingExampleApplication.class, args);
}
}
package com.example.config;
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 AsyncConfig {
@Bean(name ="taskExecutor")
public Executor taskExecutor(){
ThreadPoolTaskExecutor executor=new ThreadPoolTaskExecutor();
executor.setCorePoolSize(100);
executor.setMaxPoolSize(100);
executor.setQueueCapacity(2000);
executor.setThreadNamePrefix("userThread-");
executor.initialize();
return executor;
}
}
package com.example.controller;
import com.example.entity.User;
import com.example.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;
@RestController
public class UserController {
@Autowired
private UserService service;
@PostMapping(value = "/users", consumes = {MediaType.MULTIPART_FORM_DATA_VALUE}, produces = "application/json")
public ResponseEntity saveUsers(@RequestParam(value = "files") MultipartFile[] files) throws Exception {
for (MultipartFile file : files) {
service.saveUsers(file);
}
return ResponseEntity.status(HttpStatus.CREATED).build();
}
// save and get users
@GetMapping(value = "/users", produces = "application/json")
public List<User> findAllUsers() throws ExecutionException, InterruptedException {
List<CompletableFuture<User>> userList = new ArrayList<>();
for (int i = 1; i <= 20; i++) {
service.saveUserById(i);
CompletableFuture<User> user = service.getUserById(i);
userList.add(user);
}
List<User> myUsers = new ArrayList<>();
for (CompletableFuture<User> u: userList) {
myUsers.add(u.get());
}
return myUsers;
}
// save and get users with different for loops
@GetMapping(value = "/different", produces = "application/json")
public List<User> findAllUsersEach() throws ExecutionException, InterruptedException, TimeoutException {
List<CompletableFuture<User>> userList = new ArrayList<>();
for (int i = 1; i <= 200; i++) {
service.saveUserById(i);
// CompletableFuture<User> user = service.getUserById(i);
// userList.add(user);
}
for (int i = 1; i <= 200; i++) {
// service.saveUserById(i);
CompletableFuture<User> user = service.getUserById(i);
userList.add(user);
}
List<User> myUsers = new ArrayList<>();
// loops through entire list, waits if the task is incomplete.
userList.forEach(CompletableFuture::join);
for (CompletableFuture<User> u: userList) {
// waits for 10 ms if the task is incomplete. Gets the result immediately if the task is already complete.
// myUsers.add(u.get(10, TimeUnit.MILLISECONDS));
myUsers.add(u.get());
}
return myUsers;
}
@GetMapping("/get")
public List<User> getUsersAsync() throws ExecutionException, InterruptedException {
List<CompletableFuture<User>> userList = new ArrayList<>();
for (int i = 1; i <= 1000; i++) {
CompletableFuture<User> user = service.findUserById(i);
userList.add(user);
}
List<User> myUsers = new ArrayList<>();
for (CompletableFuture<User> u: userList) {
myUsers.add(u.get());
}
return myUsers;
}
}
package com.example.entity;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import javax.persistence.*;
@Data
@Entity
@AllArgsConstructor
@NoArgsConstructor
public class User {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private int id;
private String name;
private String email;
private String gender;
}
package com.example.repository;
import com.example.entity.User;
import org.springframework.data.jpa.repository.JpaRepository;
public interface UserRepository extends JpaRepository<User,Integer> {
}
package com.example.service;
import com.example.entity.User;
import com.example.repository.UserRepository;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutionException;
@Service
public class UserService {
@Autowired
private UserRepository repository;
Object target;
Logger logger = LoggerFactory.getLogger(UserService.class);
@Async
public CompletableFuture<List<User>> saveUsers(MultipartFile file) throws Exception {
long start = System.currentTimeMillis();
List<User> users = parseCSVFile(file);
logger.info("saving list of users of size {}", users.size(), "" + Thread.currentThread().getName());
users = repository.saveAll(users);
long end = System.currentTimeMillis();
logger.info("Total time {}", (end - start));
return CompletableFuture.completedFuture(users);
}
// method that gets the user by id @Async annotation lets us run the method in a separate thread every time it is called.
@Async
public CompletableFuture<User> findUserById(int id) {
logger.info("get user with id " + id + " by " + Thread.currentThread().getName());
User user = repository.findById(id).get();
return CompletableFuture.completedFuture(user);
}
// save and get the data through a single controller asynchronously.
@Async
public void saveUserById(int id) {
User user = new User(id, "abc", "xyz@mail.com", Integer.toString(id));
repository.save(user);
logger.info("save user with id " + id + " by " + Thread.currentThread().getName());
}
@Async
public CompletableFuture<User> getUserById(int id) {
User user = null;
try{
user = repository.findById(id).get();
return CompletableFuture.completedFuture(user);
}catch (Exception ex){
logger.error(ex.getMessage());
}finally {
logger.info("get user with id " + id + " by " + Thread.currentThread().getName());
}
return null;
}
private List<User> parseCSVFile(final MultipartFile file) throws Exception {
final List<User> users = new ArrayList<>();
try {
try (final BufferedReader br = new BufferedReader(new InputStreamReader(file.getInputStream()))) {
String line;
br.readLine();
while ((line = br.readLine()) != null) {
final String[] data = line.split(",");
final User user = new User();
user.setName(data[0]);
user.setEmail(data[1]);
user.setGender(data[2]);
users.add(user);
}
return users;
}
} catch (final IOException e) {
logger.error("Failed to parse CSV file {}", e);
throw new Exception("Failed to parse CSV file {}", e);
}
}
}
server.port = 8080
spring.jpa.hibernate.ddl-auto=update
spring.jpa.defer-datasource-initialization=true
spring.sql.init.mode=always
spring.datasource.url=jdbc:mysql://localhost:3306/mydb
spring.datasource.username=root
spring.datasource.password=root1234
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
#spring.jpa.show-sql: true
package com.example;
import org.junit.jupiter.api.Test;
import org.springframework.boot.test.context.SpringBootTest;
@SpringBootTest
class SpringbootMultithreadingExampleApplicationTests {
@Test
void contextLoads() {
}
}
server.port = 8080
spring.jpa.hibernate.ddl-auto=update
spring.jpa.defer-datasource-initialization=true
spring.sql.init.mode=always
spring.datasource.url=jdbc:mysql://localhost:3306/mydb
spring.datasource.username=root
spring.datasource.password=root1234
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
#spring.jpa.show-sql: true
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment