導入
非同期処理は、特にI/O操作や外部APIとの通信が頻繁に行われる現場において、その効果を最大限に発揮します。Javaでは、非同期処理を実現するためのさまざまな手法が存在しますが、特にCompletableFutureを使用することで、非同期タスクの管理やエラーハンドリングが容易になります。本記事では、実際の業務シナリオを基にした非同期処理の実装方法について学び、その後に練習問題を通じて理解を深めます。
教科書レベルの解説(非同期処理)
重要な概念の整理
非同期処理は、タスクを実行する際に、他の処理をブロックせずに進める手法です。これにより、特にI/O待ちの時間を有効に活用できます。JavaのCompletableFutureは、非同期タスクを簡潔に扱うための強力なクラスであり、タスクの完了を待たずに次の処理を進めたり、複数のタスクを組み合わせて実行することが可能です。
この手法を使用する際の注意点として、非同期タスクの実行順序やエラーハンドリングが挙げられます。特に、タスク間の依存関係がある場合には、適切な順序で処理を行わないと、意図しない結果を招くことがあります。
コード例(Java)
import java.util.concurrent.CompletableFuture;
public class AsyncExample {
public static void main(String[] args) {
CompletableFuture future = CompletableFuture
.supplyAsync(() -> {
// 時間のかかる処理
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
return "結果";
})
.thenApply(result -> {
// 結果を利用した処理
return "処理結果: " + result;
})
.thenAccept(finalResult -> {
// 最終結果の表示
System.out.println(finalResult);
});
// メインスレッドは他の処理を続けることができる
System.out.println("非同期処理を開始しました。");
// 完了を待つ
future.join();
}
}
コードの行ごとの解説
- CompletableFutureをインポートし、メインクラスを定義します。
- 非同期処理を開始するために、supplyAsyncメソッドを使用します。ここでは、時間のかかる処理を模倣するためにThread.sleepを使用しています。
- thenApplyメソッドを使用して、最初の処理の結果を受け取り、次の処理を行います。
- thenAcceptメソッドで、最終的な結果をコンソールに出力します。
- 非同期処理が開始されたことをメインスレッドで表示し、future.join()で非同期タスクの完了を待ちます。
練習問題編
以下の練習問題に取り組んで、非同期処理の理解を深めましょう。
-
非同期処理を使用して、複数のAPIからデータを取得し、結果を統合するプログラムを作成してください。
模範解答: CompletableFutureを複数作成し、allOfメソッドを使用して全てのタスクが完了するのを待ち、結果を統合します。
-
エラーハンドリングを含む非同期処理の例を作成してください。API呼び出しが失敗した場合、適切にエラーメッセージを表示するようにしてください。
模範解答: exceptionallyメソッドを使用して、エラーが発生した場合の処理を追加します。
-
非同期処理を使用して、ファイルの読み込みとデータの加工を行うプログラムを作成してください。
模範解答: ファイルの読み込みを非同期に行い、thenApplyでデータ加工を行います。
まとめ
- 非同期処理を使用することで、I/O待ちの時間を有効活用できる。
- CompletableFutureを利用することで、非同期タスクの管理やエラーハンドリングが容易になる。
- 実際の業務シナリオに即した非同期処理の実装が重要である。