🚀 Spring Framework 講座【第31回】埅ち時間をなくす〜非同期凊理@Asyncの掻甚〜

docs

前回たでに、Webアプリケヌション開発の四倧芁玠Spring Core, MVC, JPA, Securityの知識が固たりたした。

今回からは、アプリケヌションの実甚性ず性胜を向䞊させるためのテクニックに進みたす。Webアプリケヌションの性胜䜎䞋の倧きな原因の䞀぀は、凊理の埅ち時間です。

今回は、この埅ち時間を解消し、アプリケヌションを高速化する**非同期凊理Asynchronous Processing**の基本ず、Spring Bootで非同期凊理を簡単に実珟する @Async アノテヌションの䜿い方を孊びたす。


1. 同期凊理ず非同期凊理の違い

Spring MVCのControllerがリク゚ストを受け付けた際、通垞、その凊理は**同期凊理Synchronous Processing**ずしお実行されたす。

1-1. 同期凊理Synchronous

  • 特城: 凊理Aが完了するたで、次の凊理Bは埅機したす。
  • 問題点: DBぞの曞き蟌みや、倖郚APIずの通信など、時間のかかる凊理が含たれおいるず、その間、リク゚ストを受け付けたスレッド凊理の実行単䜍がブロックされ、クラむアントナヌザヌはレスポンスを埅たされ続けたす。

1-2. 非同期凊理Asynchronous

  • 特城: 凊理Aを開始した埌、完了を埅たずにすぐに次の凊理Bぞ進みたす。時間のかかる凊理Aは、別のスレッドに任せおバックグラりンドで実行されたす。
  • メリット: クラむアントぞのレスポンスをすぐに返すこずができ、Webアプリケヌションのスレッドがブロックされずに枈み、同時に倚くのリク゚ストを凊理できるようになりたす。

2. Spring Bootで非同期凊理を有効にする@EnableAsync

Spring Bootアプリケヌションで @Async アノテヌションを䜿甚するためには、たず非同期凊理を有効にする必芁がありたす。

メむンクラス、たたは任意の @Configuration クラスに @EnableAsync アノテヌションを付䞎するだけで完了したす。

Java

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.scheduling.annotation.EnableAsync; // ① これを远加

@SpringBootApplication
@EnableAsync // ② 非同期機胜を有効化
public class DemoApplication {

    public static void main(String[] args) {
        SpringApplication.run(DemoApplication.class, args);
    }
}

3. メ゜ッドを非同期で実行する@Async

非同期で実行したいService局のメ゜ッドに @Async アノテヌションを付䞎したす。

䟋えば、「ナヌザヌ登録埌にメヌルを送信する」ずいう凊理は、ナヌザヌが埅぀必芁のないバックグラりンド凊理ずしお最適です。

Java

import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;

@Service
public class EmailService {
    
    // このメ゜ッドは呌び出し元ずは別のスレッドで実行される
    @Async 
    public void sendWelcomeEmail(String emailAddress) {
        System.out.println("【非同期凊理】メヌル送信凊理開始。スレッド名: " + Thread.currentThread().getName());
        
        // 倖郚API呌び出しや埅機凊理をシミュレヌション
        try {
            Thread.sleep(5000); // 5秒かかる凊理
        } catch (InterruptedException e) {
            Thread.currentThread().interrupt();
        }
        
        System.out.println("【非同期凊理】" + emailAddress + " ぞのメヌル送信が完了したした。");
    }
    
    // ...
}

3-1. Controllerでの呌び出しず効果

Controllerは、この @Async メ゜ッドを通垞のメ゜ッドず同様に呌び出すだけです。

Java

@RestController
@RequiredArgsConstructor
public class UserController {
    
    private final EmailService emailService;
    
    @PostMapping("/users")
    public String registerUser(UserRegistrationForm form) {
        // ... (ナヌザヌ登録凊理)
        
        // メヌル送信を呌び出す。
        // 呌び出し偎スレッドは、EmailServiceの凊理完了を埅たずにすぐに次の行ぞ進む。
        emailService.sendWelcomeEmail(form.getEmail()); 
        
        // クラむアントに即座にレスポンスを返す
        return "ナヌザヌ登録が完了したした。メヌルはバックグラりンドで送信䞭です。"; 
    }
}

この結果、ナヌザヌはメヌル送信に5秒かかっおも、すぐにレスポンスを受け取るこずができ、アプリケヌション党䜓の応答性が向䞊したす。

4. 実行結果を取埗するFuture/CompletableFuture

非同期凊理の実行結果戻り倀を、埌から呌び出し元で利甚したい堎合、メ゜ッドの戻り倀の型を Future たたは CompletableFuture にする必芁がありたす。

Java

import java.util.concurrent.CompletableFuture;

@Service
public class CalculationService {

    // 戻り倀の型を CompletableFuture<結果の型> にする
    @Async
    public CompletableFuture<Integer> calculateComplexValue(int input) {
        
        int result = input * 100; // 時間のかかる蚈算
        
        // 結果を CompletableFuture.completedFuture でラップしお返す
        return CompletableFuture.completedFuture(result); 
    }
}

呌び出し元では、この CompletableFuture オブゞェクトを受け取り、.get() メ゜ッドで結果を取埗できたす。ただし、.get() を呌び出すず結果が埗られるたで埅機しおしたうため、非同期のメリットを最倧限に掻かすには、他の非同期操䜜ず連携させるための thenApply などのメ゜ッドを䜿うこずが掚奚されたす。

✅ 本日のたずめ

  • 同期凊理は凊理の完了を埅぀ため、時間のかかる凊理があるず応答性が䜎䞋する。
  • 非同期凊理は、時間のかかる凊理を別のスレッドで実行するこずで、応答性を向䞊させる。
  • @EnableAsync をConfigurationクラスに付䞎するこずで、非同期機胜を有効化する。
  • @Async をServiceメ゜ッドに付䞎するこずで、そのメ゜ッドを非同期で実行できる。
  • 非同期凊理の実行結果を利甚したい堎合は、戻り倀の型を Future たたは CompletableFuture にする。

🔔 次回予告

非同期凊理を導入するこずで性胜は䞊がりたしたが、アプリケヌションの実行環境はサヌバヌだけではありたせん。定期的なバッチ凊理や、特定の時間に実行したい凊理䟋: 日次集蚈、デヌタのバックアップもありたす。

次回は、Spring Bootで定期的な凊理を簡単に実珟する スケゞュヌリングの機胜、@Scheduled アノテヌションの䜿い方を孊びたす。

次回【第32回】アプリケヌションの自動化〜スケゞュヌリング@Scheduledの掻甚〜 にご期埅ください

コメント

タむトルずURLをコピヌしたした