概要
RubyでFutureパターンを実装する
内容
Futureパターンは実行結果を得るまでに時間がかかる処理をする際に
結果の代わりに引換券をもらいます。
例えばドラクエの購入をする際に予約がなければ発売当日にずっと並ばなければなりません。
ここで予約をしておけば予約券を受け取って実際に発売日が来たら受け取ることが可能です。
当日受け取り時間が遅れたとすれば待機することになります。
補足
※補足実際はこの例より簡単に実装可能。
あくまでパターンの理解を優先してRubyの言語側で
用意してくれている仕組みは利用せずに処理します。
簡易実装版については以下参照
RubyでFutureパターンを実装する(シンプル編)
plantUMLソース
@startuml{future_pattern.png} title Future Pattern class Main class Host { request } class FutureData { realdata getContent() setRealData() } class RealData { content getContent() } interface Data { getContent() } Main --> Host : Request Main --> Data : Uses in future Host --> FutureData : Creates FutureData ..|> Data RealData ..|> Data FutureData o-- RealData @enduml
サンプルコード
# encoding: utf-8 require 'thread' class Host def request(id, value) future_data = FutureData.new Thread.start do # 時間のかかる処理を想定 sleep id real_data = RealData.new(id, value); future_data.set_real_data(real_data); end return future_data end end class RealData def initialize(id, value) @id, @value = id, value end def get_content() return @id, @value end end class FutureData def initialize() @complete = false @real_data = nil @mutex = Mutex.new @cv = ConditionVariable.new end def complete? @complete end def complete! @complete = true end def set_real_data(real_data) @mutex.synchronize do return if complete? @real_data = real_data complete! @cv.broadcast end end def get_content() @mutex.synchronize do @cv.wait(@mutex) while (!complete?) return @real_data.get_content() end end end host = Host.new() puts Time.now future1 = host.request(1, 'hoge') future2 = host.request(2, 'hige') future3 = host.request(10, 'hage') puts Time.now # 時間のかかる処理を想定 sleep(5) ret1 = future1.get_content() ret2 = future2.get_content() ret3 = future3.get_content() puts Time.now print ret1 puts print ret2 puts print ret3 puts
出力
スレッド内部でidに指定した時間待機が発生していますが
Futureの取得前後では全く処理時間がかかっていないことがわかります。
その後、5秒待機させていますが待機中もスレッドの処理が進行しているため
最終処理時間は15秒にならずに10秒になっています。
スレッドを利用せずに実行するのに比べて5秒節約出来ています。
2013-06-23 01:07:28 +0900 2013-06-23 01:07:28 +0900 2013-06-23 01:07:38 +0900 [1, "hoge"] [2, "hige"] [10, "hage"]