[JAVA] Asynchrone Verarbeitung mit Spring Boot unter Verwendung von @Async

Über dieses Dokument

Ich habe untersucht, was für die asynchrone Verarbeitung mit SpringBoot erforderlich ist.

  1. Asynchrone Verarbeitungsmethode mit @Async
  2. Einrichten von Threads mit TaskExcecuter

Ich fasste zusammen.

Ausführungsumgebung

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')
}

Versuchen

Implementieren Sie den Prozess, den Sie asynchron ausführen möchten

Implementierung

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);
    }

}
Kommentar

Implementieren Sie den Prozess des Aufrufs und der Behandlung der obigen Logik

Implementierung

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;
    }

}
Kommentar

Stellen Sie die Obergrenze für Thread usw. ein.

Implementierung

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;
    }

}
Kommentar

Lauf

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

Grobe Zusammenfassung

Impressionen

Referenzierte Materialien

Recommended Posts

Asynchrone Verarbeitung mit Spring Boot unter Verwendung von @Async
Asynchrone Verarbeitung mit regelmäßiger Ausführung in Spring Boot
Feder mit Kotorin --6 Asynchrone Verarbeitung
Versuchen Sie es mit Spring Boot mit VS-Code
Mit Spring Boot herunterladen
Führen Sie nach der Standardauthentifizierung mit Spring Boot eine beliebige Verarbeitung aus.
Versuchen Sie es mit einem DI-Container mit Laravel und Spring Boot
Generieren Sie mit Spring Boot einen Barcode
Hallo Welt mit Spring Boot
Implementieren Sie GraphQL mit Spring Boot
Versuchen Sie, OpenID Connect mit Keycloak (Spring Boot-Anwendung) zu verwenden.
Beginnen Sie mit Spring Boot
[JUnit 5-kompatibel] Schreiben Sie einen Test mit JUnit 5 mit Spring Boot 2.2, 2.3
Hallo Welt mit Spring Boot!
Datei-Upload mit Spring Boot
Spring Boot beginnt mit dem Kopieren
Verwenden von Mapper mit Java (Spring)
Spring Boot beginnend mit Docker
Hallo Welt mit Spring Boot
Setzen Sie Cookies mit Spring Boot
Verwenden Sie Spring JDBC mit Spring Boot
Modul mit Spring Boot hinzufügen
Erste Schritte mit Spring Boot
Versuchen Sie es mit Spring Boot Security
[Swift] Asynchrone Verarbeitung mit PromiseKit
Erstellen Sie mit Spring Boot einen Mikrodienst
Mail mit Spring Boot verschicken
Ausführen der Erstverarbeitung mit Spring Boot Command Line Runner
Ich habe versucht, mit Swagger mit Spring Boot zu beginnen
Verwenden Sie die Standardauthentifizierung mit Spring Boot
gRPC auf Spring Boot mit grpc-spring-boot-Starter
Erstellen Sie eine App mit Spring Boot 2
Hot Deploy mit Spring Boot-Entwicklung
Datenbankverknüpfung mit doma2 (Spring Boot)
Spring Boot Tutorial Verwenden der Spring Security-Authentifizierung
Spring Boot Programmierung mit VS Code
Bis "Hallo Welt" mit Spring Boot
Erstellen Sie eine Anfrage-App mit Spring Boot
Erhalten Sie Validierungsergebnisse mit Spring Boot
(Intellij) Hallo Welt mit Spring Boot
Erstellen Sie eine App mit Spring Boot
Google Cloud Platform mit Spring Boot 2.0.0
Ich habe GraphQL mit Spring Boot ausprobiert
[Java] LINE-Integration mit Spring Boot
Beginnend mit Spring Boot 0. Verwenden Sie Spring CLI
Ich habe Flyway mit Spring Boot ausprobiert
Die Nachrichtenkooperation begann mit Spring Boot
Teil 1: Versuchen Sie, die von Spring Security 5 unterstützte OAuth 2.0-Anmeldung mit Spring Boot zu verwenden
Stellen Sie sich die Spring Boot-App mit dem Jib-Maven-Plugin vor und starten Sie sie mit Docker
Hallo Welt mit Eclipse + Spring Boot + Maven
Senden Sie regelmäßige Benachrichtigungen mit LineNotify + Spring Boot
HTTPS mit Spring Boot und Let's Encrypt
Starten Sie die Entwicklung von Webanwendungen mit Spring Boot
Starten Sie die Nginx + Spring Boot-Anwendung mit Docker-Compose
Ich habe Lazy Initialization mit Spring Boot 2.2.0 ausprobiert
Implementieren Sie CRUD mit Spring Boot + Thymeleaf + MySQL
Implementieren Sie die Paging-Funktion mit Spring Boot + Thymeleaf
(IntelliJ + gradle) Hallo Welt mit Spring Boot