Asynkrone metoder med @Async
Lær at udføre metoder asynkront ved hjælp af Springs `@Async`-annotation og trådpools.
Asynkrone metoder med @Async er en gratis Komplet guide til Spring Boot 4-lektion på CoddyKit. Dette er lektion 1 af 4. Du kan læse alle 3 lektioner i dette læringsspor gratis i deres fulde længde — derefter låser CoddyKit PRO alle lektioner op samt praktiske øvelser med en indbygget kodeeditor og en AI-underviser døgnet rundt. Den er en del af læringsforløbet i Komplet guide til Spring Boot 4, og dine fremskridt synkroniseres på tværs af nettet og CoddyKit-appen. Komplet guide til Spring Boot 4-kurset indeholder 4 lektioner i alt.
Introduktion til asynkrone operationer
Forestil dig, at du bestiller mad online. Hvis appen tvang dig til at vente på, at kokken tilberedte din mad, før du overhovedet kunne se andre muligheder, ville det være en dårlig oplevelse!
Det svarer til synkrone operationer: én opgave skal være færdig, før den næste kan begynde. Det blokerer hovedforløbet.
Asynkrone operationer lader dig derimod starte en opgave og straks gå videre til noget andet. Opgaven kører i baggrunden, og du får besked, når den er færdig.
- Ikke-blokerende: Din applikation forbliver responsiv.
- Effektiv: Ressourcerne udnyttes bedre, fordi flere opgaver udføres samtidigt.
Demo: Synkron versus asynkron
Lad os se på et enkelt Java-eksempel på en blokerende (synkron) operation. Bemærk, hvordan hovedtråden venter på, at doSyncTask() bliver færdig.
Prøv at køre dette eksempel:
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!");
}
}
}Mød Springs @Async
Spring Boot gør det utroligt enkelt at omdanne en synkron metode til en asynkron metode ved hjælp af annotationen @Async.
Når du annoterer en metode med @Async:
- Udfører Spring metoden i en separat tråd.
- Returnerer den kaldende metode med det samme uden at vente på, at
@Async-metoden bliver færdig. - Du behøver ikke selv at administrere tråde!
Aktivér @Async
Før du kan bruge @Async, skal du aktivere asynkron behandling i din Spring Boot-applikation. Det gør du ved at tilføje annotationen @EnableAsync.
Du placerer typisk @EnableAsync på din hovedapplikationsklasse eller på en dedikeret konfigurationsklasse.
Sådan tilføjer du den:
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!");
}
}Grundlæggende om @Async-metoder
Når @EnableAsync er på plads, kan du blot tilføje @Async til enhver offentlig metode i en Spring-administreret komponent (f.eks. en @Service eller @Component).
Når der kaldes på performAsyncTask(), udskriver hovedtråden straks sin næste linje, mens den asynkrone opgave kører i baggrunden.
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.");
}
}
}Sådan fungerer @Async
Når du bruger @Async, opretter Spring ikke en ny tråd for hvert kald. I stedet bruger den en trådpulje.
- En trådpulje er en samling forhåndsinitialiserede tråde, der kan udføre opgaver.
- Når der kaldes på en
@Async-metode, henter Spring en ledig tråd fra puljen til at udføre den. - Det undgår omkostningerne ved konstant at oprette nye tråde og administrerer systemressourcerne effektivt.
- Som standard bruger Spring en
SimpleAsyncTaskExecutor, som kan være ineffektiv ved stor belastning.
Hent resultater med Future
Hvad nu, hvis din asynkrone metode skal returnere et resultat til den kaldende kode? Du kan ikke bare returnere void eller en direkte værdi.
Til det bruger du java.util.concurrent.Future. Objektet Future fungerer som en pladsholder for et resultat, der endnu ikke er tilgængeligt.
@Async-metoden returnererFuture<T>(f.eks.Future<String>).- Den kaldende kode kan senere kalde
future.get()for at hente resultatet (dette kald blokerer, indtil resultatet er klar). - Du kan også kontrollere
future.isDone()for at se, om opgaven er fuldført, uden at blokere.
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!");
}
}
}Håndtering af asynkrone fejl
Når en @Async-metode (især en void-metode) kaster en undtagelse, bliver den som standard ikke videreført til den kaldende tråd. Det betyder, at undtagelsen muligvis bliver ignoreret uden besked, hvilket gør fejlfinding vanskelig.
Hvis du vil håndtere undtagelser korrekt i @Async-metoder, kan du implementere AsyncConfigurer og angive en brugerdefineret AsyncUncaughtExceptionHandler.
- Denne håndtering fanger alle undtagelser, der kastes af
@Async-metoder. - Den giver dig mulighed for at logge fejl, sende meddelelser eller udføre andre handlinger til fejlhåndtering.
- For metoder, der returnerer
Future, pakkes undtagelsen ind iFutureog kastes, nårfuture.get()kaldes.
Brugerdefineret trådpulje
I produktionsapplikationer er det afgørende at konfigurere din egen trådpulje (Executor) til @Async. Det giver dig kontrol over ressourcer og ydeevne.
Du definerer en ThreadPoolTaskExecutor-bean og angiver dens egenskaber:
corePoolSize: Det mindste antal tråde, der skal holdes aktive.maxPoolSize: Det maksimale antal tråde, puljen kan indeholde.queueCapacity: Køens kapacitet til opgaver, der venter på at blive udført.threadNamePrefix: Et præfiks til navnene på trådene i denne pulje, hvilket er nyttigt til logning.
Derefter kan du angive, hvilken executor der skal bruges, med @Async("executorBeanName").
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() { /* ... */ }
}Hurtigt tjek af asynkronitet
Lad os tjekke, om du har forstået Springs annotering @Async.
Opsummering af lektionen
Godt klaret! Du har lært det grundlæggende om asynkron behandling med Spring Boots @Async.
- Vi så, hvordan synkrone operationer blokerer, mens asynkrone operationer tillader ikke-blokerende udførelse.
- Annotationen
@EnableAsyncaktiverer behandling af asynkrone metoder. - Annotationen
@Asyncpå en metode sikrer, at den kører i en separat tråd. - Til returnering af resultater fra asynkrone metoder bruger vi
Future<T>. - Brugerdefinerede
ThreadPoolTaskExecutor-beans giver finmasket kontrol over trådpuljens funktionsmåde.
Nu dykker vi ned i meddelelseskøer, som er en effektiv måde at afkoble tjenester og håndtere asynkron kommunikation i større skala på.
Lær Java med en AI-underviser — gratis
Skriv og kør rigtig kode i din browser, få øjeblikkelig hjælp fra en AI-underviser døgnet rundt, og fortsæt, hvor du slap, på web eller i appen.
- Kurser
- 21
- Lektioner
- 84
Ofte stillede spørgsmål
Er lektionen “Asynkrone metoder med @Async” gratis?
Ja — alle 3 lektioner i læringssporet Komplet guide til Spring Boot 4, inklusive “Asynkrone metoder med @Async”, kan læses gratis i deres fulde længde her på webstedet. Derefter låser CoddyKit PRO alle lektioner op samt interaktive øvelser med en indbygget kodeeditor og en AI-underviser døgnet rundt. Komplet guide til Spring Boot 4-kurset indeholder 4 lektioner i alt.
Hvad lærer jeg i “Asynkrone metoder med @Async”?
Lær at udføre metoder asynkront ved hjælp af Springs `@Async`-annotation og trådpools. Du øver dig i Komplet guide til Spring Boot 4 med praktisk kode, som du kører direkte i browseren, og en AI-vejleder døgnet rundt besvarer dine spørgsmål, mens du arbejder dig gennem lektionen.
Skal jeg have erfaring for at begynde på Komplet guide til Spring Boot 4?
Der kræves ingen tidligere erfaring. Komplet guide til Spring Boot 4 på CoddyKit er tilrettelagt for både begyndere og øvede, så du kan starte her eller fra begyndelsen og lære i dit eget tempo. Dette er lektion 1 af 4.
Hvor lang tid tager lektionen “Asynkrone metoder med @Async”?
De fleste CoddyKit-lektioner tager cirka 5–10 minutter. Hver lektion er kort og interaktiv, så du gør løbende fremskridt og kan fortsætte, hvor du slap – på både web og app.
Kan jeg skrive og køre kode i denne Komplet guide til Spring Boot 4-lektion?
Ja. Alle Komplet guide til Spring Boot 4-lektioner har en indbygget kodeeditor, så du kan skrive og køre rigtig kode direkte i din browser og få øjeblikkelig feedback fra AI – uden lokal opsætning.
Alle lektioner i dette kursus
- Asynkrone metoder med @Async
- Introduktion til message queues
- Integration af RabbitMQ/Kafka
- Planlægning af opgaver med @Scheduled