コールバックとフューチャーの基本と活用方法

callback-future

今日のトピックは「コールバック」と「フューチャー」についてです。これらは、非同期プログラミングにおいて非常に重要な概念であり、効率的に並行処理を行うために使われます。コールバックは非同期操作の結果を処理するための関数であり、フューチャーは非同期操作の結果を保持するオブジェクトです。

目次

基本概念の説明

コールバック (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クラスでフューチャーを管理します。asyncawaitを使うことで非同期処理を簡潔に記述できます。

C++: 標準ライブラリのstd::functionを使ってコールバックを実装し、std::futureでフューチャーを使用して非同期処理の結果を受け取ります。

Java: CompletableFutureを使ってコールバックとフューチャーを管理します。非同期処理が完了した後にコールバックが呼び出されます。

まとめ

コールバックとフューチャーは、非同期プログラミングにおける重要な手法です。コールバックは処理完了時に実行される関数であり、フューチャーは非同期処理の結果を保持するオブジェクトです。これらを適切に使い分けることで、効率的な並行処理が可能になります。

次回は、さらに高度な非同期処理のパターンや、リアクティブプログラミングについて学びましょう。

よかったらシェアしてね!
  • URLをコピーしました!
  • URLをコピーしました!

コメント

コメントする

目次