Spring Boot 4 – komplett guide · Lektion

Asynkrona metoder med @Async

Lär er att köra metoder asynkront med Spring:s `@Async`-annotation och trådpooler.

Lektion 1 av 411 steg

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 returnerar Future<T> (till exempel Future<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 Future kapslas undantaget in i Future och kastas när future.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 @EnableAsync aktiverar bearbetning av asynkrona metoder.
  • Annoteringen @Async på 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 ThreadPoolTaskExecutor ger 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.

Gratis att börja

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

  1. Asynkrona metoder med @Async
  2. Introduktion till meddelandeköer
  3. Integrering av RabbitMQ/Kafka
  4. Schemalägg uppgifter med @Scheduled
← Tillbaka till Spring Boot 4 – komplett guide