今日のトピックは「コールバック」と「フューチャー」についてです。これらは、非同期プログラミングにおいて非常に重要な概念であり、効率的に並行処理を行うために使われます。コールバックは非同期操作の結果を処理するための関数であり、フューチャーは非同期操作の結果を保持するオブジェクトです。
基本概念の説明
コールバック (Callback)
コールバック (Callback): コールバックは、非同期操作が完了した後に実行される関数です。非同期処理中にコールバック関数を指定しておくことで、処理が完了した際に自動的にその関数が呼び出されます。
フューチャー (Future)
フューチャー (Future): フューチャーは、非同期処理の結果を保持するオブジェクトです。処理が完了すると、フューチャーを通じてその結果を取得できます。フューチャーは、処理の完了を待つために使われることが多く、コールバックと組み合わせて使われることもあります。
各言語でのコールバックとフューチャーの使用例
Python:
import threading
import concurrent.futures
# コールバックの使用
def async_operation(callback):
def run():
result = "データ処理完了"
callback(result) # コールバック関数を呼び出す
threading.Thread(target=run).start()
def handle_result(result):
print(f"コールバックで結果を受け取りました: {result}")
async_operation(handle_result)
# フューチャーの使用
def async_task():
return "フューチャーによる結果"
with concurrent.futures.ThreadPoolExecutor() as executor:
future = executor.submit(async_task)
print(f"フューチャーで結果を受け取りました: {future.result()}")
C#:
using System;
using System.Threading;
using System.Threading.Tasks;
class Program
{
// コールバックの使用
static void AsyncOperation(Action callback)
{
new Thread(() =>
{
Thread.Sleep(1000); // 擬似的な非同期処理
callback("データ処理完了");
}).Start();
}
static void HandleResult(string result)
{
Console.WriteLine($"コールバックで結果を受け取りました: {result}");
}
// フューチャーの使用
static async Task AsyncTask()
{
await Task.Delay(1000); // 擬似的な非同期処理
return "フューチャーによる結果";
}
static async Task Main(string[] args)
{
// コールバックの使用
AsyncOperation(HandleResult);
// フューチャーの使用
string result = await AsyncTask();
Console.WriteLine($"フューチャーで結果を受け取りました: {result}");
}
}
C++:
#include <iostream>
#include <thread>
#include <future>
// コールバックの使用
void async_operation(std::function<void(std::string)> callback) {
std::thread([callback]() {
std::this_thread::sleep_for(std::chrono::seconds(1)); // 擬似的な非同期処理
callback("データ処理完了");
}).detach();
}
void handle_result(const std::string& result) {
std::cout << "コールバックで結果を受け取りました: " << result << std::endl;
}
// フューチャーの使用
std::string async_task() {
std::this_thread::sleep_for(std::chrono::seconds(1)); // 擬似的な非同期処理
return "フューチャーによる結果";
}
int main() {
// コールバックの使用
async_operation(handle_result);
// フューチャーの使用
std::future<std::string> future = std::async(std::launch::async, async_task);
std::cout << "フューチャーで結果を受け取りました: " << future.get() << std::endl;
return 0;
}
Java:
import java.util.concurrent.CompletableFuture;
class AsyncExample {
// コールバックの使用
public static void asyncOperation(java.util.function.Consumer<String> callback) {
new Thread(() -> {
try {
Thread.sleep(1000); // 擬似的な非同期処理
} catch (InterruptedException e) {
e.printStackTrace();
}
callback.accept("データ処理完了");
}).start();
}
// フューチャーの使用
public static CompletableFuture<String> asyncTask() {
return CompletableFuture.supplyAsync(() -> {
try {
Thread.sleep(1000); // 擬似的な非同期処理
} catch (InterruptedException e) {
e.printStackTrace();
}
return "フューチャーによる結果";
});
}
public static void main(String[] args) {
// コールバックの使用
asyncOperation(result -> System.out.println("コールバックで結果を受け取りました: " + result));
// フューチャーの使用
asyncTask().thenAccept(result -> System.out.println("フューチャーで結果を受け取りました: " + result));
}
}
各言語の解説
Python: コールバック関数を非同期処理の後で呼び出し、concurrent.futures
を使ってフューチャーを管理します。
C#: Action
デリゲートを使用してコールバックを実装し、Task
クラスでフューチャーを管理します。async
とawait
を使うことで非同期処理を簡潔に記述できます。
C++: 標準ライブラリのstd::function
を使ってコールバックを実装し、std::future
でフューチャーを使用して非同期処理の結果を受け取ります。
Java: CompletableFuture
を使ってコールバックとフューチャーを管理します。非同期処理が完了した後にコールバックが呼び出されます。
まとめ
コールバックとフューチャーは、非同期プログラミングにおける重要な手法です。コールバックは処理完了時に実行される関数であり、フューチャーは非同期処理の結果を保持するオブジェクトです。これらを適切に使い分けることで、効率的な並行処理が可能になります。
次回は、さらに高度な非同期処理のパターンや、リアクティブプログラミングについて学びましょう。
コメント