カテゴリ: Spring 更新日: 2026/07/01

Springの@Async入門ガイド!非同期処理と戻り値を初心者向けに解説

@Async 入門:メソッド非同期化と戻り値(CompletableFuture など)
@Async 入門:メソッド非同期化と戻り値(CompletableFuture など)

先生と生徒の会話形式で理解しよう

生徒

「Spring Bootで処理を非同期で実行したいんですけど、どうすればいいですか?」

先生

「それなら@Asyncアノテーションを使うのが便利ですよ。処理を別スレッドで実行できるようになります。」

生徒

「戻り値のあるメソッドでも使えますか?」

先生

「はい、CompletableFutureなどを使えば戻り値付きの非同期処理も簡単にできます。それでは、詳しく解説していきましょう!」

1. Springの@Asyncとは?

「1. Springの@Asyncとは?」の重要ポイントを、初心者の方にも分かりやすく簡潔に解説します。

1. Springの@Asyncとは?
1. Springの@Asyncとは?

Spring Frameworkには、簡単に非同期処理を実現できる@Asyncというアノテーションが用意されています。このアノテーションをメソッドに付けることで、そのメソッドは別スレッドで非同期に実行されるようになります。

例えば、重い処理やバッチ処理、APIの並列呼び出しなどをメインスレッドの負荷をかけずに処理したい場合に便利です。

2. @EnableAsyncで非同期処理を有効にする

2. @EnableAsyncで非同期処理を有効にする
2. @EnableAsyncで非同期処理を有効にする

@Asyncを使うには、まずアプリケーション全体で非同期処理を有効にする必要があります。これは@EnableAsyncアノテーションを使用することで簡単に実現できます。


import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.annotation.EnableAsync;

@Configuration
@EnableAsync
public class AsyncConfig {
}

3. 基本的な@Asyncの使い方

3. 基本的な@Asyncの使い方
3. 基本的な@Asyncの使い方

それでは、@Asyncを使って簡単な非同期メソッドを作ってみましょう。非同期処理をするクラスには@Component@Serviceを付けてSpring管理下に置きます。


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

@Service
public class AsyncService {

    @Async
    public void executeAsyncTask() {
        System.out.println("非同期処理中...");
    }
}

このexecuteAsyncTaskメソッドを呼び出すと、別スレッドで処理が実行され、メインスレッドをブロックしません。

4. 非同期メソッドの戻り値:CompletableFutureの活用

「4. 非同期メソッドの戻り値:CompletableFutureの活用」の重要ポイントを、初心者の方にも分かりやすく簡潔に解説します。

4. 非同期メソッドの戻り値:CompletableFutureの活用
4. 非同期メソッドの戻り値:CompletableFutureの活用

非同期メソッドに戻り値が必要な場合は、JavaのCompletableFutureを使います。これは非同期の結果をラップし、後から値を取得したり、連結処理を行うことができます。


import java.util.concurrent.CompletableFuture;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;

@Service
public class AsyncService {

    @Async
    public CompletableFuture<String> fetchData() {
        // 擬似的に時間のかかる処理をシミュレート
        try {
            Thread.sleep(2000);
        } catch (InterruptedException e) {
            Thread.currentThread().interrupt();
        }
        return CompletableFuture.completedFuture("データ取得完了");
    }
}

5. CompletableFutureの結果を取得する方法

5. CompletableFutureの結果を取得する方法
5. CompletableFutureの結果を取得する方法

非同期処理の結果を取得するには、呼び出し元でget()thenApply()などのメソッドを使用します。


import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutionException;

@Component
public class Caller {

    @Autowired
    private AsyncService asyncService;

    public void callAsync() throws ExecutionException, InterruptedException {
        CompletableFuture<String> future = asyncService.fetchData();
        String result = future.get(); // 結果をブロッキングで取得
        System.out.println("結果:" + result);
    }
}

注意:このget()は結果が返ってくるまで待機するため、完全な非同期とは言えません。本当に非同期で完結させたい場合は、thenAccept()などのコールバックを使います。

6. スレッドプールのカスタマイズ

6. スレッドプールのカスタマイズ
6. スレッドプールのカスタマイズ

Springでは、デフォルトで非同期処理用のスレッドプールが提供されていますが、アプリケーションの規模に応じてスレッド数やキューサイズを調整した方がパフォーマンスが安定します。


import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.annotation.AsyncConfigurer;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;

import java.util.concurrent.Executor;

@Configuration
public class AsyncThreadConfig implements AsyncConfigurer {

    @Override
    @Bean("customExecutor")
    public Executor getAsyncExecutor() {
        ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
        executor.setCorePoolSize(3);       // コアスレッド数
        executor.setMaxPoolSize(10);       // 最大スレッド数
        executor.setQueueCapacity(100);    // キューサイズ
        executor.setThreadNamePrefix("AsyncThread-");
        executor.initialize();
        return executor;
    }
}

そして非同期メソッド側で、使用するExecutorを指定することも可能です。


@Async("customExecutor")
public void customAsyncTask() {
    // カスタムスレッドで非同期処理
}

7. 例外処理とAsyncUncaughtExceptionHandler

「7. 例外処理とAsyncUncaughtExceptionHandler」の重要ポイントを、初心者の方にも分かりやすく簡潔に解説します。

7. 例外処理とAsyncUncaughtExceptionHandler
7. 例外処理とAsyncUncaughtExceptionHandler

@Asyncで例外が発生した場合、通常のtry-catchでは捕捉できないケースがあります。特にvoid戻り値の非同期メソッドでは、AsyncUncaughtExceptionHandlerを使って例外を処理します。


import org.springframework.aop.interceptor.AsyncUncaughtExceptionHandler;
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.annotation.AsyncConfigurer;

import java.lang.reflect.Method;
import java.util.concurrent.Executor;

@Configuration
public class AsyncExceptionConfig implements AsyncConfigurer {

    @Override
    public Executor getAsyncExecutor() {
        return null; // 必要に応じてExecutorを設定
    }

    @Override
    public AsyncUncaughtExceptionHandler getAsyncUncaughtExceptionHandler() {
        return new AsyncUncaughtExceptionHandler() {
            @Override
            public void handleUncaughtException(Throwable ex, Method method, Object... params) {
                System.err.println("非同期例外:" + ex.getMessage());
            }
        };
    }
}

8. 非同期処理の活用シーン

8. 非同期処理の活用シーン
8. 非同期処理の活用シーン

Springの@Asyncを使うと、以下のようなシーンで効果を発揮します。

  • メール送信処理
  • ログの記録
  • 外部APIの呼び出し
  • 重い計算やバッチ処理

メイン処理のレスポンス速度を改善したいとき、非同期処理は非常に有効な手段です。

9. 実行結果のイメージ

9. 実行結果のイメージ
9. 実行結果のイメージ

非同期処理がうまく動いていれば、呼び出し元のログよりも先に非同期処理がバックグラウンドで開始されます。


結果:データ取得完了

まとめ

「まとめ」の重要ポイントを、初心者の方にも分かりやすく簡潔に解説します。

まとめ
まとめ

Springの非同期処理とAsyncの重要ポイントを整理

Spring BootやSpring Frameworkにおける非同期処理は、アプリケーションのパフォーマンス改善やユーザー体験向上において非常に重要な役割を持っています。その中でもAsyncアノテーションは、初心者でも比較的簡単に非同期処理を実現できる便利な仕組みです。メソッドにAsyncを付与するだけで別スレッドで処理が実行されるため、重たい処理や時間のかかる外部API呼び出しをメイン処理から切り離すことができます。

特にWebアプリケーションでは、レスポンス速度がユーザー満足度に直結するため、メール送信処理やログ保存、データ取得などを非同期化することで、画面表示の高速化が可能になります。こうした非同期処理の設計は、実務レベルのSpring開発において必須の知識と言えるでしょう。

EnableAsyncと基本設定の理解が第一歩

Asyncを利用するためには、まずEnableAsyncを設定する必要があります。この設定を行わないと、Asyncを付与しても非同期処理として動作しないため注意が必要です。設定自体は非常にシンプルですが、初心者が見落としやすいポイントでもあります。

また、SpringのDIコンテナ管理下にあるクラスでなければAsyncは有効にならないため、ServiceやComponentのアノテーションも正しく付与する必要があります。この仕組みを理解しておくことで、なぜ動かないのかというトラブルを未然に防ぐことができます。

CompletableFutureで戻り値付き非同期処理を実現

非同期処理で戻り値を扱いたい場合には、CompletableFutureを使用するのが一般的です。このクラスは非同期処理の結果を保持し、後から取得したり、処理を連結したりすることができます。単純なgetによる取得だけでなく、thenApplyやthenAcceptなどを使うことで、より高度な非同期処理の構築が可能になります。

ただし、getを使用すると処理が完了するまで待機するため、非同期のメリットが失われる場合があります。完全に非同期として扱うためには、コールバック形式のメソッドを活用することが重要です。この点は初心者がつまずきやすい部分なので、しっかり理解しておきましょう。

スレッドプール設定とパフォーマンス最適化

Springではデフォルトのスレッドプールが用意されていますが、本格的な開発ではカスタマイズが重要になります。スレッド数やキューサイズを適切に設定することで、負荷の高いシステムでも安定した動作を実現できます。

特に大量の非同期処理を扱う場合、スレッド数が不足すると処理が遅延したり、逆に多すぎるとリソースを圧迫する可能性があります。適切なチューニングを行うことで、効率的な非同期処理を実現することができます。

例外処理とデバッグのポイント

Asyncを使用した非同期処理では、通常のtry catchで例外を捕捉できないケースがあります。そのため、AsyncUncaughtExceptionHandlerを利用して例外処理を行うことが重要です。特にvoid型のメソッドでは例外が見えにくくなるため、ログ出力などをしっかり設定しておく必要があります。

また、非同期処理はデバッグが難しいため、ログを適切に出力し、スレッドの動きを把握することが重要です。初心者のうちは、まずシンプルな構成で動作確認を行い、徐々に複雑な処理へと拡張していくのがおすすめです。

サンプルプログラムで動きを確認


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

@Service
public class SampleAsyncService {

    @Async
    public void sendMail() {
        System.out.println("メール送信処理を非同期で実行中");
    }
}

メール送信処理を非同期で実行中

このように、Asyncを付けるだけで非同期処理が実行されるため、初心者でもすぐに実装できるのが大きな魅力です。まずは簡単な処理から試してみることで、非同期の動きを体感することができます。

HTMLでの補足説明例


<div class="alert alert-success">
    <strong>非同期処理のポイント</strong>
    Asyncを使うことで処理を高速化しユーザー体験を向上させることができます。
</div>

このようにBootstrapを活用することで、重要なポイントを視覚的に強調することができ、読者にとって理解しやすい記事構成になります。見やすさも重要な要素の一つです。

先生と生徒の振り返り会話

生徒

「Asyncを使うと処理が速くなる理由がわかりましたメイン処理とは別で動くんですね」

先生

「そうです別スレッドで動くことでユーザーの待ち時間を減らすことができます」

生徒

「CompletableFutureを使えば戻り値も扱えるのが便利ですね」

先生

「その通りです非同期処理でも結果を扱えるのが重要なポイントです」

生徒

「スレッドプールの設定も大事なんですね」

先生

「はいパフォーマンスに直結するため実務では必ず調整します」

生徒

「例外処理が少し難しそうですが慣れていきたいです」

先生

「最初はログをしっかり確認しながら進めれば大丈夫です少しずつ理解を深めていきましょう」

生徒

「非同期処理の基礎がしっかり理解できました」

先生

「とても良いですねAsyncを使いこなせれば実務でも大きな強みになります」

Spring FrameworkやThymeleafを使った Webアプリ開発の全体像をやさしく理解したい人には、 この入門書が定番です。

Spring Framework超入門をAmazonで見る

※ Amazon広告リンク

カテゴリの一覧へ
新着記事
New1
Spring
Spring の@RequestParamの使い方!テキストボックス、ラジオボタン、チェックボックス、セレクトボックスの値を受け取る。
更新記事
New2
JSP
EL式の基本構文まとめ!${}で使う書き方のルールを解説
更新記事
New3
Java
JavaのBigIntegerとisProbablePrimeメソッドを完全解説!初心者でもわかる素数判定
更新記事
New4
JSP
JSPで発生する主なエラーとは?初心者向けに原因と対処法をやさしく解説
新規投稿
人気記事
No.1
Java&Spring記事人気No1
JSP
JSPのおすすめ学習・用語まとめ【2026年最新版】初心者が知っておきたい基本をやさしく解説
No.2
Java&Spring記事人気No2
Java
Javaのクラスとインスタンス化、コンストラクタの使い方完全ガイド!初心者でもわかるオブジェクト指向の基礎
No.3
Java&Spring記事人気No3
Spring
Springの@Serviceアノテーションの使い方を徹底解説!初心者でもわかるSpring フレームワーク入門
No.4
Java&Spring記事人気No4
Spring
Thymeleaf(タイムリーフ)入門!初心者でもわかるSpring Bootとテンプレートエンジンの使い方
No.5
Java&Spring記事人気No5
Spring
Javaの@PreAuthorizeアノテーションを完全ガイド!初心者でもわかるメソッドセキュリティ設定
No.6
Java&Spring記事人気No6
Spring
Springの@Queryアノテーションを徹底解説!初心者でもわかるSpring Bootのカスタムクエリ
No.7
Java&Spring記事人気No7
Java
JavaのExceptionクラスを完全解説!初心者でも理解できる例外処理の基本
No.8
Java&Spring記事人気No8
JSP
JSPでCSSやJSを読み込む基本!外部ファイルのパス指定に注意しよう