Asynchrone methoden met @Async
Leer methoden asynchroon uit te voeren met Spring's `@Async`-annotatie en threadpools.
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
@Asyncis 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
@Asyncwordt 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
@AsyncretourneertFuture<T>(bijvoorbeeldFuture<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
@Asyncworden opgeworpen. - Je kunt hiermee fouten registreren, meldingen verzenden of andere acties voor fout herstel uitvoeren.
- Bij methoden die
Futureretourneren, wordt de uitzondering verpakt in deFutureen opgeworpen wanneerfuture.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
@EnableAsyncactiveert asynchrone verwerking van methoden. - De annotatie
@Asyncop 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.
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
- Asynchrone methoden met @Async
- Inleiding tot message queues
- RabbitMQ/Kafka integreren
- Taken plannen met @Scheduled