Complete gids voor Spring Boot 4 · Les

Asynchrone methoden met @Async

Leer methoden asynchroon uit te voeren met Spring's `@Async`-annotatie en threadpools.

Les 1 van 411 stappen

Asynchrone methoden met @Async is een gratis Complete gids voor Spring Boot 4-les op CoddyKit. Dit is les 1 van 4. Je kunt 3 lessen uit dit leerpad gratis volledig lezen — daarna ontgrendelt CoddyKit PRO alle lessen, plus praktische oefeningen met een ingebouwde code-editor en een AI-tutor die 24/7 beschikbaar is. Deze les maakt deel uit van het leertraject Complete gids voor Spring Boot 4. Je voortgang wordt gesynchroniseerd op het web en in de CoddyKit-app. De cursus Complete gids voor Spring Boot 4 bevat in totaal 4 lessen.

Introductie tot asynchrone bewerkingen

Stel je voor dat je online eten bestelt. Als de app je zou laten wachten tot de kok je maaltijd heeft bereid voordat je andere opties kunt bekijken, zou dat een slechte ervaring zijn!

Dit lijkt op synchrone bewerkingen: één taak moet zijn voltooid voordat de volgende kan beginnen. De hoofdstroom wordt geblokkeerd.

Asynchrone bewerkingen stellen je daarentegen in staat een taak te starten en meteen verder te gaan met iets anders. De taak draait op de achtergrond en je krijgt een melding wanneer deze klaar is.

  • Niet-blokkerend: Je toepassing blijft responsief.
  • Efficiënt: Resources worden beter benut doordat meerdere taken gelijktijdig worden uitgevoerd.

Demonstratie van synchroon versus asynchroon

Laten we een eenvoudig Java-voorbeeld van een blokkerende (synchrone) bewerking bekijken. Let erop hoe de hoofdthread wacht totdat doSyncTask() is voltooid.

Probeer dit voorbeeld uit te voeren:

public class Main {
  public static void main(String[] args) {
    System.out.println("Main thread: Starting sync task...");
    long startTime = System.currentTimeMillis();
    doSyncTask(); // This call blocks the main thread
    long endTime = System.currentTimeMillis();
    System.out.println("Main thread: Sync task finished in " + (endTime - startTime) + "ms.");
    System.out.println("Main thread: Continues immediately after sync task.");
  }

  public static void doSyncTask() {
    try {
      System.out.println("Sync task: Simulating work for 2 seconds...");
      Thread.sleep(2000); // Simulate a long operation
      System.out.println("Sync task: Completed!");
    } catch (InterruptedException e) {
      Thread.currentThread().interrupt();
      System.err.println("Sync task: Interrupted!");
    }
  }
}

Kennismaken met Spring's @Async

Spring Boot maakt het bijzonder eenvoudig om een synchrone methode om te zetten in een asynchrone methode met de annotatie @Async.

Wanneer je een methode annoteert met @Async:

  • Voert Spring die methode uit in een afzonderlijke thread.
  • Keert de aanroepende methode onmiddellijk terug, zonder te wachten totdat de methode met @Async is voltooid.
  • Je hoeft threads niet handmatig te beheren!

@Async activeren

Voordat je @Async kunt gebruiken, moet je asynchrone verwerking inschakelen in je Spring Boot-toepassing. Dit doe je door de annotatie @EnableAsync toe te voegen.

Je plaatst @EnableAsync meestal op je hoofdtoepassingsklasse of op een speciale configuratieklasse.

Zo voeg je de annotatie toe:

package com.coddykit.async;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.scheduling.annotation.EnableAsync;

@SpringBootApplication
@EnableAsync // This annotation activates @Async capability
public class AsyncApplication {
  public static void main(String[] args) {
    SpringApplication.run(AsyncApplication.class, args);
    System.out.println("Spring Boot application started with @EnableAsync!");
  }
}

Basisprincipes van @Async-methoden

Wanneer @EnableAsync is ingesteld, kun je eenvoudig @Async toevoegen aan elke publieke methode in een door Spring beheerd component (zoals een @Service of @Component).

Wanneer performAsyncTask() wordt aangeroepen, drukt de hoofdthread onmiddellijk de volgende regel af, terwijl de asynchrone taak op de achtergrond wordt uitgevoerd.

package com.coddykit.async;

import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;
import org.springframework.boot.CommandLineRunner;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.Bean;
import org.springframework.scheduling.annotation.EnableAsync;

@SpringBootApplication
@EnableAsync
public class AsyncApplication {
  public static void main(String[] args) {
    SpringApplication.run(AsyncApplication.class, args);
  }

  @Bean
  public CommandLineRunner run(MyAsyncTaskService service) {
    return args -> {
      System.out.println("Main thread: Calling async task...");
      service.performAsyncTask(); // This call returns immediately
      System.out.println("Main thread: Async task called, continuing immediately.");
      // Give the async task a chance to finish before the app exits
      Thread.sleep(3000);
    };
  }
}

@Service
class MyAsyncTaskService {
  @Async // Mark this method to run asynchronously
  public void performAsyncTask() {
    try {
      System.out.println("Async thread: Starting long task...");
      Thread.sleep(2000); // Simulate a long operation
      System.out.println("Async thread: Long task completed!");
    } catch (InterruptedException e) {
      Thread.currentThread().interrupt();
      System.err.println("Async thread: Task interrupted.");
    }
  }
}

Hoe @Async werkt

Wanneer je @Async gebruikt, maakt Spring niet voor elke aanroep een nieuwe thread. In plaats daarvan gebruikt het een threadpool.

  • Een threadpool is een verzameling vooraf geïnitialiseerde threads die taken kunnen uitvoeren.
  • Wanneer een methode met @Async wordt aangeroepen, haalt Spring een beschikbare thread uit de pool om de methode uit te voeren.
  • Zo vermijd je de overhead van het voortdurend aanmaken van nieuwe threads en worden systeemresources efficiënt beheerd.
  • Standaard gebruikt Spring een SimpleAsyncTaskExecutor, wat inefficiënt kan zijn bij zware belasting.

Resultaten ophalen met Future

Wat als je asynchrone methode een resultaat moet teruggeven aan de aanroeper? Je kunt niet zomaar void of een directe waarde retourneren.

Hiervoor gebruik je java.util.concurrent.Future. Het object Future fungeert als tijdelijke aanduiding voor een resultaat dat nog niet beschikbaar is.

  • De methode met @Async retourneert Future<T> (bijvoorbeeld Future<String>).
  • De aanroepende code kan later future.get() aanroepen om het resultaat op te halen (deze aanroep blokkeert totdat het resultaat gereed is).
  • Je kunt ook future.isDone() controleren om te zien of de taak is voltooid, zonder te blokkeren.
package com.coddykit.async;

import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;
import org.springframework.boot.CommandLineRunner;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.Bean;
import org.springframework.scheduling.annotation.EnableAsync;
import java.util.concurrent.Future;
import java.util.concurrent.AsyncResult;

@SpringBootApplication
@EnableAsync
public class AsyncApplication {
  public static void main(String[] args) {
    SpringApplication.run(AsyncApplication.class, args);
  }

  @Bean
  public CommandLineRunner run(MyFutureTaskService service) {
    return args -> {
      System.out.println("Main thread: Calling async task with Future...");
      Future<String> futureResult = service.performFutureTask();
      System.out.println("Main thread: Async task called, continuing immediately.");

      // Main thread can do other work while async task runs
      System.out.println("Main thread: Doing other work...");
      Thread.sleep(500);

      // Wait for the result (this loop checks, future.get() blocks)
      while(!futureResult.isDone()) {
        System.out.println("Main thread: Waiting for async result...");
        Thread.sleep(500);
      }
      String result = futureResult.get(); // Retrieves the result (blocks if not done)
      System.out.println("Main thread: Received result: " + result);
    };
  }
}

@Service
class MyFutureTaskService {
  @Async
  public Future<String> performFutureTask() {
    try {
      System.out.println("Async thread: Starting Future task...");
      Thread.sleep(2000); // Simulate a long operation
      System.out.println("Async thread: Future task completed!");
      return new AsyncResult<>("Task finished successfully!");
    } catch (InterruptedException e) {
      Thread.currentThread().interrupt();
      return new AsyncResult<>("Task interrupted!");
    }
  }
}

Foutafhandeling bij asynchrone bewerkingen

Wanneer een methode met @Async (vooral een methode die void retourneert) een uitzondering opwerpt, wordt deze standaard niet doorgegeven aan de aanroepende thread. Dit betekent dat de uitzondering mogelijk stil wordt genegeerd, waardoor het opsporen van fouten moeilijk wordt.

Om uitzonderingen in methoden met @Async correct af te handelen, kun je AsyncConfigurer implementeren en een aangepaste AsyncUncaughtExceptionHandler bieden.

  • Deze handler vangt alle uitzonderingen op die door methoden met @Async worden opgeworpen.
  • Je kunt hiermee fouten registreren, meldingen verzenden of andere acties voor fout herstel uitvoeren.
  • Bij methoden die Future retourneren, wordt de uitzondering verpakt in de Future en opgeworpen wanneer future.get() wordt aangeroepen.

Aangepaste threadpool

Voor productietoepassingen is het essentieel om je eigen threadpool (Executor) voor @Async te configureren. Zo krijg je controle over resources en prestaties.

Je definieert een ThreadPoolTaskExecutor-bean en geeft de eigenschappen ervan op:

  • corePoolSize: Het minimale aantal threads dat actief blijft.
  • maxPoolSize: Het maximale aantal threads dat de pool kan bevatten.
  • queueCapacity: De capaciteit van de wachtrij voor taken die wachten op uitvoering.
  • threadNamePrefix: Een voorvoegsel voor de namen van threads in deze pool, wat handig is voor logregistratie.

Vervolgens kun je met @Async("executorBeanName") opgeven welke executor moet worden gebruikt.

package com.coddykit.async;

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 = "customAsyncExecutor")
  public Executor customAsyncExecutor() {
    ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
    executor.setCorePoolSize(2); // Keep 2 threads always running
    executor.setMaxPoolSize(5);  // Allow up to 5 threads if demand is high
    executor.setQueueCapacity(10); // Queue up to 10 tasks if all threads are busy
    executor.setThreadNamePrefix("CustomAsync-"); // Helps identify threads in logs
    executor.initialize();
    return executor;
  }

  // To use this, you'd annotate your async method like this:
  // @Async("customAsyncExecutor")
  // public void myCustomAsyncMethod() { /* ... */ }
}

Korte controle van asynchrone bewerkingen

Laten we controleren of je de annotatie @Async van Spring begrijpt.

Samenvatting van de les

Goed gedaan! Je hebt de basisprincipes geleerd van asynchrone verwerking met @Async van Spring Boot.

  • We hebben gezien hoe synchrone bewerkingen blokkeren, terwijl asynchrone bewerkingen niet-blokkerende uitvoering mogelijk maken.
  • De annotatie @EnableAsync activeert asynchrone verwerking van methoden.
  • De annotatie @Async op een methode zorgt ervoor dat deze in een afzonderlijke thread wordt uitgevoerd.
  • Voor het retourneren van resultaten uit asynchrone methoden gebruiken we Future<T>.
  • Aangepaste ThreadPoolTaskExecutor-beans bieden gedetailleerde controle over het gedrag van de threadpool.

Vervolgens duiken we in berichtenwachtrijen, een krachtige manier om services los te koppelen en asynchrone communicatie op grotere schaal af te handelen.

Gratis beginnen

Leer Java met een AI-tutor — gratis

Schrijf echte code en voer die uit in je browser, krijg direct hulp van een AI-tutor die 24/7 beschikbaar is en ga verder waar je gebleven bent op het web of in de app.

Cursussen
21
Lessen
84

Veelgestelde vragen

Is de les “Asynchrone methoden met @Async” gratis?

Ja — je kunt hier op het web alle 3 lessen van het leerpad Complete gids voor Spring Boot 4, waaronder “Asynchrone methoden met @Async”, gratis volledig lezen. Daarna ontgrendelt CoddyKit PRO alle lessen, plus interactieve oefeningen met een ingebouwde code-editor en een AI-tutor die 24/7 beschikbaar is. De cursus Complete gids voor Spring Boot 4 bevat in totaal 4 lessen.

Wat leer ik in “Asynchrone methoden met @Async”?

Leer methoden asynchroon uit te voeren met Spring's `@Async`-annotatie en threadpools. Je oefent met Complete gids voor Spring Boot 4 door code rechtstreeks in de browser uit te voeren. Een AI-begeleider die 24/7 beschikbaar is beantwoordt je vragen terwijl je de les doorwerkt.

Heb ik ervaring nodig om met Complete gids voor Spring Boot 4 te beginnen?

Ervaring vooraf is niet nodig. Complete gids voor Spring Boot 4 op CoddyKit is opgebouwd voor beginners tot gevorderden, zodat je hier of bij het begin kunt starten en in je eigen tempo kunt leren. Dit is les 1 van 4.

Hoe lang duurt de les “Asynchrone methoden met @Async”?

De meeste lessen van CoddyKit duren ongeveer 5–10 minuten. Elke les is kort en interactief, zodat je gestaag vooruitgaat en op het web en in de app precies verdergaat waar je was gebleven.

Kan ik code schrijven en uitvoeren in deze les over Complete gids voor Spring Boot 4?

Ja. Elke les over Complete gids voor Spring Boot 4 bevat een ingebouwde code-editor, zodat je rechtstreeks in je browser echte code kunt schrijven en uitvoeren en direct feedback van AI krijgt — lokale installatie is niet nodig.

Alle lessen in deze cursus

  1. Asynchrone methoden met @Async
  2. Inleiding tot message queues
  3. RabbitMQ/Kafka integreren
  4. Taken plannen met @Scheduled
← Terug naar Complete gids voor Spring Boot 4