@Asyncとは
「非同期でメソッドを実行するためのアノテーション」 のことです。
通常、Javaのメソッドは呼び出し元が処理完了を待って次の行へ進みますが、@Async
を使うことでメソッドを別のスレッドで実行し、呼び出し元は待たずに次の処理に進めるようになります。
例えば、メール送信やファイルのアップロード処理など、ユーザーの待ち時間を減らしたいケースで効果を発揮します。
基本的な使い方
それでは、実際に @Async
を使った例を見てみましょう。以下のコードを見てください。
@Service
public class NotificationService {
@Async
public void sendEmail(String email) {
// 実際にはメールを送信する処理
System.out.println("Sending email to " + email);
try {
Thread.sleep(3000); // メール送信に3秒かかると仮定
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
System.out.println("Email sent to " + email);
}
}
説明
@Async
アノテーションをsendEmail()
メソッドに付与することで、このメソッドは非同期に実行されます。- 実行するたびに新しいスレッドが作られるため、呼び出し元は待たずに次の処理へ進むことができます。
呼び出し例
@Autowired
private NotificationService notificationService;
notificationService.sendEmail("example@example.com");
System.out.println("次の処理を実行中...");
この場合、「次の処理を実行中…」がすぐに表示され、その後に「Sending email to example@example.com」が続きます。つまり、メール送信が非同期で処理されます。
@Asyncの設定方法
1. @EnableAsync を追加する
@Async
を使用するためには、Spring Bootアプリケーションの設定クラス(通常は @SpringBootApplication
が付与されているクラス)に @EnableAsync
アノテーションを付ける必要があります。
@SpringBootApplication
@EnableAsync
public class MyApplication {
public static void main(String[] args) {
SpringApplication.run(MyApplication.class, args);
}
}
2. 非同期メソッドの戻り値
非同期メソッドには、戻り値として void
以外に CompletableFuture
や Future
を指定することができます。これにより、非同期処理の結果を受け取ることが可能です。
@Async
public CompletableFuture<String> fetchData() {
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
return CompletableFuture.completedFuture("データ取得完了");
}
呼び出し例
CompletableFuture<String> future = notificationService.fetchData();
future.thenAccept(result -> System.out.println(result));
@Asyncの応用編
1. 非同期メソッドに引数を渡す
@Async
メソッドは引数を持つことができ、通常のメソッドと同様に値を渡すことが可能です。
@Async
public void processTask(int taskId) {
System.out.println("Processing task: " + taskId);
}
2. 複数の非同期メソッドの同時実行
複数の @Async
メソッドを同時に呼び出すことで、並列処理を実現できます。
notificationService.sendEmail("user1@example.com");
notificationService.sendEmail("user2@example.com");
notificationService.sendEmail("user3@example.com");
各メール送信処理が別々のスレッドで実行されるため、全体の処理が高速化されます。
3. 例外処理
非同期メソッド内で例外が発生しても、デフォルトでは呼び出し元に通知されません。必要に応じて、 AsyncUncaughtExceptionHandler
を実装して例外をキャッチすることができます。
@Component
public class AsyncExceptionHandler implements AsyncUncaughtExceptionHandler {
@Override
public void handleUncaughtException(Throwable ex, Method method, Object... params) {
System.out.println("Exception in method: " + method.getName() + ", Message: " + ex.getMessage());
}
}
@EnableAsync
@Configuration
public class AppConfig implements AsyncConfigurer {
@Override
public AsyncUncaughtExceptionHandler getAsyncUncaughtExceptionHandler() {
return new AsyncExceptionHandler();
}
}
@Asyncの引数
1. value属性でExecutorを指定
@Async
アノテーションには value
属性を使って、使用する Executor を指定することができます。
@Async("customExecutor")
public void performAsyncTask() {
// カスタムExecutorで非同期処理
}
customExecutor
は、以下のように設定します。
@Bean(name = "customExecutor")
public Executor taskExecutor() {
ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
executor.setCorePoolSize(5);
executor.setMaxPoolSize(10);
executor.setQueueCapacity(25);
executor.initialize();
return executor;
}
2. Timeoutの設定
非同期処理にタイムアウトを設定したい場合、 @Transactional(timeout)
を併用して管理することができます。
おわりに
使いどころ
@Async
は、以下のようなシナリオで役立ちます:
- 非同期なAPIリクエストの処理: ユーザーが待つ必要のない処理(例: ログの保存、メール通知など)を非同期化。
- バッチ処理: 複数のデータを並行して処理。
- レスポンスタイムの向上: ユーザーにすぐ応答を返したいが、裏で時間のかかる処理を行いたいとき。
まとめ
今回は、Springの @Async
について詳しく見てきました。非同期処理を簡単に導入できる便利なツールで、アプリケーションのパフォーマンス向上に大いに役立ちます。ぜひ、この機会に @Async
を活用して、効率的なWebアプリケーション開発を進めてください!
もっと詳しく知りたい方は、Spring公式ドキュメントを見てみてくださいね。
他の記事が見たい方はこちら!↓↓↓
@GroupSequenceの使い方と引数を徹底解説!【初心者向け】
@AssertTrueと@AssertFalseの使い方と違いを徹底解説!【初心者向け】
@Max, @Min, @Sizeアノテーションの使い方と違いを解説!【初心者向け】