Asynkrona metoder med @Async
Lär er att köra metoder asynkront med Spring:s `@Async`-annotation och trådpooler.
Asynkrona metoder med @Async är en gratis lektion i Spring Boot 4 – komplett guide på CoddyKit. Detta är lektion 1 av 4. Du kan läsa vilka 3 lektioner som helst i den här lärvägen kostnadsfritt i sin helhet – därefter låser CoddyKit PRO upp alla lektioner, plus praktisk övning med en inbyggd kodredigerare och en AI-lärare dygnet runt. Den ingår i lärvägen för Spring Boot 4 – komplett guide, och Era framsteg synkroniseras mellan webben och CoddyKit-appen. Kursen i Spring Boot 4 – komplett guide innehåller totalt 4 lektioner.
Introduktion till asynkrona operationer
Föreställ Er att Ni beställer mat på nätet. Om appen tvingade Er att vänta på att kocken skulle laga maten innan Ni ens kunde se andra alternativ, skulle det vara en dålig upplevelse!
Detta liknar synkrona operationer: en uppgift måste slutföras innan nästa kan starta. Det blockerar huvudflödet.
Asynkrona operationer låter Er däremot starta en uppgift och genast gå vidare till något annat. Uppgiften körs i bakgrunden och Ni får en avisering när den är klar.
- Icke-blockerande: Applikationen förblir responsiv.
- Effektiva: Resurserna utnyttjas bättre genom att flera uppgifter utförs samtidigt.
Demo: synkront kontra asynkront
Låt oss titta på ett enkelt Java-exempel med en blockerande (synkron) operation. Observera hur huvudtråden väntar på att doSyncTask() ska slutföras.
Prova att köra detta exempel:
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öt Springs @Async
Spring Boot gör det mycket enkelt att omvandla en synkron metod till en asynkron med hjälp av annoteringen @Async.
När Ni annoterar en metod med @Async:
- kör Spring metoden i en separat tråd.
- returnerar den anropande metoden omedelbart, utan att vänta på att
@Async-metoden ska slutföras. - behöver Ni inte hantera trådar manuellt!
Aktivera @Async
Innan Ni kan använda @Async måste Ni aktivera asynkron bearbetning i Spring Boot-applikationen. Detta görs genom att lägga till annoteringen @EnableAsync.
Vanligtvis placerar Ni @EnableAsync i applikationens huvudklass eller i en särskild konfigurationsklass.
Så här lägger Ni till 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!");
}
}Grunderna i @Async-metoder
När @EnableAsync är på plats kan Ni helt enkelt lägga till @Async i valfri publik metod i en Spring-hanterad komponent (till exempel en @Service eller @Component).
När performAsyncTask() anropas skriver huvudtråden omedelbart ut nästa rad, medan den asynkrona uppgiften körs i bakgrunden.
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å fungerar @Async
När Ni använder @Async skapar Spring inte en ny tråd för varje anrop. I stället använder ramverket en trådpool.
- En trådpool är en samling förinitierade trådar som kan köra uppgifter.
- När en
@Async-metod anropas hämtar Spring en tillgänglig tråd från poolen för att köra den. - Detta undviker kostnaden för att ständigt skapa nya trådar och hanterar systemresurserna effektivt.
- Som standard använder Spring
SimpleAsyncTaskExecutor, vilket kan vara ineffektivt vid hög belastning.
Hämta resultat med Future
Vad händer om den asynkrona metoden behöver returnera ett resultat till den som anropar den? Ni kan inte bara returnera void eller ett direkt värde.
För detta använder Ni java.util.concurrent.Future. Objektet Future fungerar som en platshållare för ett resultat som ännu inte är tillgängligt.
@Async-metoden returnerarFuture<T>(till exempelFuture<String>).- Den anropande koden kan senare anropa
future.get()för att hämta resultatet (detta anrop blockerar tills resultatet är klart). - Ni kan även kontrollera
future.isDone()för att se om uppgiften har slutförts utan att blockera.
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!");
}
}
}Felhantering vid asynkron körning
När en @Async-metod (särskilt en metod av typen void) kastar ett undantag vidarebefordras det som standard inte till den anropande tråden. Det innebär att undantaget kan försvinna tyst, vilket gör felsökning svår.
För att hantera undantag i @Async-metoder korrekt kan Ni implementera AsyncConfigurer och tillhandahålla en anpassad AsyncUncaughtExceptionHandler.
- Denna hanterare fångar alla undantag som kastas av
@Async-metoder. - Den gör det möjligt att logga fel, skicka aviseringar eller utföra andra åtgärder för felåterställning.
- För metoder som returnerar
Futurekapslas undantaget in iFutureoch kastas närfuture.get()anropas.
Anpassad trådpool
För produktionsapplikationer är det viktigt att konfigurera en egen trådpool (Executor) för @Async. Det ger Er kontroll över resurser och prestanda.
Ni definierar en bean av typen ThreadPoolTaskExecutor och anger dess egenskaper:
corePoolSize: Det minsta antalet trådar som ska hållas aktiva.maxPoolSize: Det största antalet trådar poolen får innehålla.queueCapacity: Kökapaciteten för uppgifter som väntar på att köras.threadNamePrefix: Ett prefix för namnen på trådarna i poolen, vilket är användbart vid loggning.
Därefter kan Ni ange vilken executor som ska användas 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() { /* ... */ }
}Snabbtest om asynkron körning
Låt oss kontrollera Era kunskaper om Springs annotering @Async.
Lektionssammanfattning
Bra jobbat! Ni har lärt Er grunderna i asynkron bearbetning med Spring Boots @Async.
- Vi såg hur synkrona operationer blockerar, medan asynkrona operationer möjliggör icke-blockerande körning.
- Annoteringen
@EnableAsyncaktiverar bearbetning av asynkrona metoder. - Annoteringen
@Asyncpå en metod säkerställer att den körs i en separat tråd. - För att returnera resultat från asynkrona metoder använder vi
Future<T>. - Anpassade beans av typen
ThreadPoolTaskExecutorger detaljerad kontroll över trådpoolens beteende.
Härnäst går vi igenom meddelandeköer, ett kraftfullt sätt att frikoppla tjänster och hantera asynkron kommunikation i större skala.
Lär dig Java med en AI-lärare – gratis
Skriv och kör riktig kod i webbläsaren, få omedelbar hjälp av en AI-lärare dygnet runt och fortsätt där du slutade – på webben eller i appen.
- Kurser
- 21
- Lektioner
- 84
Vanliga frågor
Är lektionen ”Asynkrona metoder med @Async” gratis?
Ja – du kan läsa vilka 3 lektioner som helst i lärvägen Spring Boot 4 – komplett guide, inklusive ”Asynkrona metoder med @Async”, kostnadsfritt i sin helhet här på webben. Därefter låser CoddyKit PRO upp alla lektioner, plus interaktiv övning med en inbyggd kodredigerare och en AI-lärare dygnet runt. Kursen i Spring Boot 4 – komplett guide innehåller totalt 4 lektioner.
Vad lär jag mig i ”Asynkrona metoder med @Async”?
Lär er att köra metoder asynkront med Spring:s `@Async`-annotation och trådpooler. Ni övar på Spring Boot 4 – komplett guide med praktisk kod som körs direkt i webbläsaren, medan en AI-handledare som är tillgänglig dygnet runt svarar på Era frågor under lektionen.
Behöver jag någon erfarenhet för att börja lära mig Spring Boot 4 – komplett guide?
Du behöver inga förkunskaper. Utbildningen i Spring Boot 4 – komplett guide på CoddyKit är upplagd för allt från nybörjare till avancerade elever, så att du kan börja här eller från början och gå fram i din egen takt. Detta är lektion 1 av 4.
Hur lång tid tar lektionen ”Asynkrona metoder med @Async”?
De flesta CoddyKit-lektioner tar cirka 5–10 minuter. Varje lektion är kort och interaktiv, så att du gör stadiga framsteg och kan fortsätta precis där du slutade – på webben eller i appen.
Kan jag skriva och köra kod i den här Spring Boot 4 – komplett guide-lektionen?
Ja. Varje Spring Boot 4 – komplett guide-lektion innehåller en inbyggd kodredigerare, så att du kan skriva och köra riktig kod direkt i webbläsaren och få omedelbar AI-feedback – utan lokal installation.
Alla lektioner i den här kursen
- Asynkrona metoder med @Async
- Introduktion till meddelandeköer
- Integrering av RabbitMQ/Kafka
- Schemalägg uppgifter med @Scheduled