Komplett guide til Spring Boot 4 · leksjon

Asynkrone metoder med @Async

Lær å kjøre metoder asynkront ved hjelp av Spring sin `@Async`-annotasjon og trådpulter.

Leksjon 1 av 411 trinn

Asynkrone metoder med @Async er en gratis leksjon i Komplett guide til Spring Boot 4 på CoddyKit. Dette er leksjon 1 av 4. Du kan lese valgfritt 3 leksjoner fra denne læringsstien gratis i sin helhet – deretter låser CoddyKit PRO opp alle leksjoner, samt praktisk øving med en innebygd kodeeditor og en AI-veileder som er tilgjengelig døgnet rundt. Den er en del av læringsløpet i Komplett guide til Spring Boot 4, og fremdriften din synkroniseres mellom nettet og CoddyKit-appen. Kurset i Komplett guide til Spring Boot 4 inneholder totalt 4 leksjoner.

Introduksjon til asynkrone operasjoner

Forestill Dem at De bestiller mat på nettet. Hvis appen tvang Dem til å vente på at kokken skulle lage maten før De kunne se på andre alternativer, ville det vært en dårlig brukeropplevelse!

Dette ligner synkrone operasjoner: Én oppgave må fullføres før den neste kan starte. Hovedflyten blokkeres.

Asynkrone operasjoner lar Dem derimot starte en oppgave og umiddelbart gå videre til noe annet. Oppgaven kjører i bakgrunnen, og De får beskjed når den er ferdig.

  • Ikke-blokkerende: Applikasjonen forblir responsiv.
  • Effektivt: Ressursene utnyttes bedre ved å utføre flere oppgaver samtidig.

Demonstrasjon av synkron og asynkron kjøring

La oss se på et enkelt Java-eksempel på en blokkerende (synkron) operasjon. Legg merke til hvordan hovedtråden venter på at doSyncTask() skal bli ferdig.

Prøv å kjøre dette eksempelet:

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 gjør det svært enkelt å gjøre en synkron metode om til en asynkron metode ved hjelp av annotasjonen @Async.

Når De annoterer en metode med @Async:

  • Utfører Spring metoden i en separat tråd.
  • Returnerer den kallende metoden umiddelbart, uten å vente på at @Async-metoden skal bli ferdig.
  • De trenger ikke å administrere tråder manuelt!

Aktivere @Async

Før De kan bruke @Async, må De aktivere asynkron behandling i Spring Boot-applikasjonen. Dette gjør De ved å legge til annotasjonen @EnableAsync.

Vanligvis plasserer De @EnableAsync på hovedklassen for applikasjonen eller i en dedikert konfigurasjonsklasse.

Slik legger De den til:

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!");
  }
}

Grunnleggende om @Async-metoder

Når @EnableAsync er på plass, kan De ganske enkelt legge til @Async på en offentlig metode i en Spring-administrert komponent (for eksempel en @Service eller @Component).

Når performAsyncTask() kalles, skriver hovedtråden ut den neste linjen umiddelbart, mens den asynkrone oppgaven kjører i bakgrunnen.

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.");
    }
  }
}

Slik fungerer @Async

Når De bruker @Async, oppretter ikke Spring en ny tråd for hvert kall. I stedet bruker den en trådpool.

  • En trådpool er en samling forhåndsinitialiserte tråder som kan utføre oppgaver.
  • Når en @Async-metode kalles, henter Spring en tilgjengelig tråd fra poolen for å utføre den.
  • Dette unngår kostnadene ved å opprette nye tråder hele tiden og sørger for effektiv håndtering av systemressurser.
  • Som standard bruker Spring en SimpleAsyncTaskExecutor, som kan være lite effektiv ved stor belastning.

Hent resultater med Future

Hva om den asynkrone metoden må returnere et resultat til den som kaller den? De kan ikke bare returnere void eller en direkte verdi.

Til dette bruker De java.util.concurrent.Future. Future-objektet fungerer som en plassholder for et resultat som ikke er tilgjengelig ennå.

  • @Async-metoden returnerer Future<T> (for eksempel Future<String>).
  • Koden som kaller metoden, kan senere kalle future.get() for å hente resultatet (dette kallet blokkerer til resultatet er klart).
  • De kan også kontrollere future.isDone() for å se om oppgaven er fullført, uten å blokkere.
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!");
    }
  }
}

Feilhåndtering ved asynkron kjøring

Når en @Async-metode (særlig en metode som returnerer void) utløser et unntak, videreføres det som standard ikke til tråden som kalte metoden. Det betyr at unntaket kan bli svelget i stillhet, noe som gjør feilsøking vanskelig.

For å håndtere unntak i @Async-metoder på riktig måte kan De implementere AsyncConfigurer og angi en egendefinert AsyncUncaughtExceptionHandler.

  • Dette håndteringsobjektet fanger opp alle unntak som utløses av @Async-metoder.
  • Det gjør det mulig å logge feil, sende varsler eller utføre andre tiltak for feilretting.
  • For metoder som returnerer Future, pakkes unntaket inn i Future og utløses når future.get() kalles.

Egendefinert trådpool

I produksjonsapplikasjoner er det viktig å konfigurere en egen trådpool (Executor) for @Async. Dette gir Dem kontroll over ressurser og ytelse.

De definerer en ThreadPoolTaskExecutor-bean og angir egenskapene:

  • corePoolSize: Det minste antallet tråder som skal holdes aktive.
  • maxPoolSize: Det maksimale antallet tråder poolen kan inneholde.
  • queueCapacity: Kapasiteten til køen for oppgaver som venter på å bli utført.
  • threadNamePrefix: Et prefiks for navnene på trådene i denne poolen, nyttig ved logging.

Deretter kan De angi hvilken executor som skal brukes, 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() { /* ... */ }
}

Rask sjekk av asynkron kjøring

La oss sjekke forståelsen Deres av Springs annotasjon @Async.

Oppsummering av leksjonen

Godt gjort! De har lært det grunnleggende om asynkron behandling med Spring Boots @Async.

  • Vi så hvordan synkrone operasjoner blokkerer, mens asynkrone operasjoner muliggjør ikke-blokkerende kjøring.
  • Annotasjonen @EnableAsync aktiverer asynkron behandling av metoder.
  • Annotasjonen @Async på en metode sørger for at den kjører i en separat tråd.
  • For å returnere resultater fra asynkrone metoder bruker vi Future<T>.
  • Egendefinerte ThreadPoolTaskExecutor-bønner gir detaljert kontroll over hvordan trådpoolen oppfører seg.

Deretter skal vi se nærmere på meldingskøer, som er en effektiv måte å koble tjenester fra hverandre på og håndtere asynkron kommunikasjon i større skala.

Gratis å komme i gang

Lær deg Java med en AI-veileder – gratis

Skriv og kjør ekte kode i nettleseren, få umiddelbar hjelp fra en AI-veileder som er tilgjengelig døgnet rundt, og fortsett der du slapp – på nettet eller i appen.

Kurs
21
Leksjoner
84

Ofte stilte spørsmål

Er leksjonen «Asynkrone metoder med @Async» gratis?

Ja – du kan lese valgfritt 3 av leksjonene i læringsstien Komplett guide til Spring Boot 4, inkludert «Asynkrone metoder med @Async», gratis i sin helhet her på nettet. Deretter låser CoddyKit PRO opp alle leksjoner, samt interaktiv øving med en innebygd kodeeditor og en AI-veileder som er tilgjengelig døgnet rundt. Kurset i Komplett guide til Spring Boot 4 inneholder totalt 4 leksjoner.

Hva lærer jeg i «Asynkrone metoder med @Async»?

Lær å kjøre metoder asynkront ved hjelp av Spring sin `@Async`-annotasjon og trådpulter. Du øver på Komplett guide til Spring Boot 4 med praktisk kode som du kjører direkte i nettleseren, mens en AI-veileder som er tilgjengelig døgnet rundt, svarer på spørsmålene dine mens du jobber deg gjennom leksjonen.

Trenger jeg erfaring for å begynne med Komplett guide til Spring Boot 4?

Ingen tidligere erfaring er nødvendig. Komplett guide til Spring Boot 4 på CoddyKit er lagt opp for både nybegynnere og viderekomne, så De kan begynne her eller helt fra start og lære i Deres eget tempo. Dette er leksjon 1 av 4.

Hvor lang tid tar leksjonen «Asynkrone metoder med @Async»?

De fleste CoddyKit-leksjoner tar omtrent 5–10 minutter. Hver leksjon er kort og interaktiv, slik at De gjør jevne fremskritt og kan fortsette akkurat der De slapp – både på nettet og i appen.

Kan jeg skrive og kjøre kode i denne Komplett guide til Spring Boot 4-leksjonen?

Ja. Alle Komplett guide til Spring Boot 4-leksjoner har en innebygd kodeeditor, slik at De kan skrive og kjøre ekte kode direkte i nettleseren og få umiddelbar tilbakemelding fra AI – uten lokal konfigurering.

Alle leksjonene i dette kurset

  1. Asynkrone metoder med @Async
  2. Introduksjon til meldingskøer
  3. Integrasjon av RabbitMQ/Kafka
  4. Planlegg oppgaver med @Scheduled
← Tilbake til Komplett guide til Spring Boot 4