Ich habe untersucht, was für die asynchrone Verarbeitung mit SpringBoot erforderlich ist.
Ich fasste zusammen.
java8 + Spring Boot 2.1.0 + lombok
build.gradle ist wie folgt
buildscript {
ext {
springBootVersion = '2.1.0.RELEASE'
}
repositories {
mavenCentral()
}
dependencies {
classpath("org.springframework.boot:spring-boot-gradle-plugin:${springBootVersion}")
}
}
apply plugin: 'java'
apply plugin: 'eclipse'
apply plugin: 'org.springframework.boot'
apply plugin: 'io.spring.dependency-management'
group = 'com.example'
version = '0.0.1-SNAPSHOT'
sourceCompatibility = 1.8
repositories {
mavenCentral()
}
dependencies {
implementation('org.springframework.boot:spring-boot-starter-web')
compileOnly('org.projectlombok:lombok')
testImplementation('org.springframework.boot:spring-boot-starter-test')
}
Erstellen Sie einen Prozess, der nur richtig schläft
@Slf4j
@Service
public class AsyncService {
@Async("Thread2")
public CompletableFuture<String> findName(String name, Long sleepTime) throws InterruptedException {
log.warn("Async function started. processName: " + name + "sleepTime: " + sleepTime);
Thread.sleep(sleepTime);
//Verwenden Sie den Rückgabewert, den Sie tatsächlich in der abschließbaren Zukunft verwenden möchten, damit Sie die asynchrone Verarbeitung verarbeiten können.
return CompletableFuture.completedFuture(name);
}
}
Implementieren Sie einen geeigneten Controller für die asynchrone Verarbeitung
@Slf4j
@RequiredArgsConstructor
@RestController
public class FindNameContoller {
private final AsyncService asyncService;
@GetMapping("/users/")
public List<String> findUsers() throws Exception {
long start = System.currentTimeMillis();
long heavyProcessTime = 3000L;
long lightProcessTime = 1000L;
log.warn("request started");
CompletableFuture<String> heavyProcess = asyncService.findName("heavy", heavyProcessTime);
CompletableFuture<String> lightProcess = asyncService.findName("light", lightProcessTime);
//Prozess, der ausgeführt werden soll, wenn heavyProcess abgeschlossen ist
heavyProcess.thenAcceptAsync(heavyProcessResult -> {
log.warn("finished name=" + heavyProcessResult + ", sleep = " + heavyProcessTime);
});
//Prozess, der ausgeführt werden soll, wenn lightProcess beendet ist
lightProcess.thenAcceptAsync(lightProcessResult -> {
log.warn("finished name=" + lightProcessResult + ", sleep = " + lightProcessTime);
});
//Wenn der angegebene Prozess abgeschlossen ist, werden die nachfolgenden Prozesse ausgeführt.
CompletableFuture.allOf(heavyProcess, lightProcess).join();
//Rückgabewert erstellen
List<String> names = new ArrayList<>();
names.add(heavyProcess.get());
names.add(lightProcess.get());
Thread.sleep(10L);
long end = System.currentTimeMillis();
//Geben Sie die Zeit des gesamten Prozesses aus
log.warn("request finished. time: " + ((end - start)) + "ms");
return names;
}
}
Beschreiben verschiedener Einstellungen in der Hauptanwendungsklasse
@EnableAsync
@SpringBootApplication
public class AsyncTrainingApplication {
public static void main(String[] args) {
SpringApplication.run(AsyncTrainingApplication.class, args);
}
@Bean("Thread1") //Diese Einstellung ist nicht angegeben und wird nicht verwendet
public Executor taskExecutor1() {
ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
executor.setCorePoolSize(20);
executor.setThreadNamePrefix("Thread1--");
executor.initialize();
return executor;
}
@Bean("Thread2") //Hier einstellen"Thread2"Wird auf @Async gesetzt und diese Einstellung wird verwendet
public Executor taskExecutor2() {
ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
executor.setCorePoolSize(5); //Die Standard-Thread-Größe. Wenn es überläuft, wird die Größe der Warteschlangenkapazität angezeigt
executor.setQueueCapacity(1); //Die Größe der Warteschlange. Erhöhen Sie den Faden beim Überlaufen auf die maximale Poolgröße
executor.setMaxPoolSize(500); //Festlegen, wie viel Thread erhöht werden soll. Wenn dieser Wert überschritten wird, wird der Prozess abgelehnt und eine Ausnahme ausgelöst.
executor.setThreadNamePrefix("Thread2--");
executor.initialize();
return executor;
}
@Bean("Reject") //Mit dieser Einstellung kann keine Warteschlange ausgeführt werden, der Thread kann nicht erhöht werden und eine RejectedExecutionException tritt auf.
public Executor rejectTaskExecuter() {
ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
executor.setCorePoolSize(1);
executor.setQueueCapacity(0);
executor.setMaxPoolSize(1);
executor.setThreadNamePrefix("Reject--");
executor.initialize();
return executor;
}
}
Wenn Sie den Prozess ausführen, wird das folgende Protokoll angezeigt und Sie können sehen, dass es asynchron ausgeführt wird
2018-11-27 20:19:13.181 WARN 8711 --- [nio-8080-exec-5] c.e.asynctraining.FindNameContoller : request started
2018-11-27 20:19:13.181 WARN 8711 --- [TaskExecutor-31] com.example.asynctraining.AsyncService : Async function started. processName: heavysleepTime: 3000
2018-11-27 20:19:13.182 WARN 8711 --- [TaskExecutor-32] com.example.asynctraining.AsyncService : Async function started. processName: lightsleepTime: 1000
2018-11-27 20:19:14.187 WARN 8711 --- [onPool-worker-2] c.e.asynctraining.FindNameContoller : finished name=light, sleep = 1000
2018-11-27 20:19:16.182 WARN 8711 --- [onPool-worker-2] c.e.asynctraining.FindNameContoller : finished name=heavy, sleep = 3000
2018-11-27 20:19:16.194 WARN 8711 --- [nio-8080-exec-5] c.e.asynctraining.FindNameContoller : request finished. time: 3013ms
Recommended Posts