アクティブ オブジェクト パターンは、メソッドの実行をメソッドの呼び出しから切り離す同時実行設計パターンです。このパターンの主な目的は、クライアントに同期インターフェイスを提供しながら、別のスレッドで操作を実行することによって非同期動作を導入することです。これは、メッセージ パッシング、リクエスト キュー、スケジューリング メカニズムを組み合わせて使用して実現されます。
API 呼び出しやデータベース クエリなどの計算を行う必要があるとします。私は怠け者なので、例外処理は実装しません。
def compute(x, y): time.sleep(2) # Some time taking task return x + y
以下は、アクティブ オブジェクト パターンを使用せずに同時リクエストを処理する方法の例です。
import threading import time def main(): # Start threads directly results = {} def worker(task_id, x, y): results[task_id] = compute(x, y) print("Submitting tasks...") thread1 = threading.Thread(target=worker, args=(1, 5, 10)) thread2 = threading.Thread(target=worker, args=(2, 15, 20)) thread1.start() thread2.start() print("Doing other work...") thread1.join() thread2.join() # Retrieve results print("Result 1:", results[1]) print("Result 2:", results[2]) if __name__ == "__main__": main()
スレッド管理: スレッドを直接管理すると、特にタスクの数が増えるにつれて複雑さが増します。
抽象化の欠如: クライアントは、タスク管理とビジネス ロジックを結び付けて、スレッドのライフサイクルを管理する責任があります。
スケーラビリティの問題: 適切なキューまたはスケジューリング メカニズムがなければ、タスクの実行順序を制御できません。
応答性の制限: クライアントは、結果にアクセスする前にスレッドが参加するまで待つ必要があります。
以下は、上記と同じことを行うためにスレッドとキューを使用したアクティブ オブジェクト パターンの Python 実装です。各部分を 1 つずつ説明します:
MethodRequest: メソッド、引数、および結果を保存する Future をカプセル化します。
def compute(x, y): time.sleep(2) # Some time taking task return x + y
スケジューラ: 別のスレッドで activity_queue からのリクエストを継続的に処理します。
import threading import time def main(): # Start threads directly results = {} def worker(task_id, x, y): results[task_id] = compute(x, y) print("Submitting tasks...") thread1 = threading.Thread(target=worker, args=(1, 5, 10)) thread2 = threading.Thread(target=worker, args=(2, 15, 20)) thread1.start() thread2.start() print("Doing other work...") thread1.join() thread2.join() # Retrieve results print("Result 1:", results[1]) print("Result 2:", results[2]) if __name__ == "__main__": main()
Servant: 実際のロジック (計算メソッドなど) を実装します。
class MethodRequest: def __init__(self, method, args, kwargs, future): self.method = method self.args = args self.kwargs = kwargs self.future = future def execute(self): try: result = self.method(*self.args, **self.kwargs) self.future.set_result(result) except Exception as e: self.future.set_exception(e)
プロキシ: メソッド呼び出しをリクエストに変換し、結果の Future を返します。
import threading import queue class Scheduler(threading.Thread): def __init__(self): super().__init__() self.activation_queue = queue.Queue() self._stop_event = threading.Event() def enqueue(self, request): self.activation_queue.put(request) def run(self): while not self._stop_event.is_set(): try: request = self.activation_queue.get(timeout=0.1) request.execute() except queue.Empty: continue def stop(self): self._stop_event.set() self.join()
クライアント: タスクを非同期で送信し、必要に応じて結果を取得します。
import time class Servant: def compute(self, x, y): time.sleep(2) return x + y
アクティブ オブジェクト パターンは、マルチスレッド環境で非同期操作を管理するための強力なツールです。メソッドの呼び出しを実行から分離することで、応答性、スケーラビリティが向上し、コードベースがよりクリーンになります。ある程度の複雑さと潜在的なパフォーマンスのオーバーヘッドは伴いますが、その利点により、高い同時実行性と予測可能な実行が必要なシナリオには優れた選択肢となります。ただし、その使用は当面の特定の問題によって異なります。ほとんどのパターンやアルゴリズムと同様、万能の解決策はありません。
ウィキペディア - アクティブ オブジェクト
以上が同時実行パターン: アクティブ オブジェクトの詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。