読者です 読者をやめる 読者になる 読者になる
無料で使えるシステムトレードフレームワーク「Jiji」 をリリースしました!

・OANDA Trade APIを利用した、オープンソースのシステムトレードフレームワークです。
・自分だけの取引アルゴリズムで、誰でも、いますぐ、かんたんに、自動取引を開始できます。

Queueを使ったワーカースレッド

Ruby

Queueを使うとワーカースレッドが簡単に作れます。

  • ワーカースレッド(=仕事をするスレッド)は、キューから順番に仕事を取り出して実行するスレッドです。
    • これとは別に定期的に仕事を積むスレッドがいて、
    • ワーカースレッドは↑から仕事が積まれた場合にそれを取り出して実行します。
    • 仕事がなければ、積まれるまで待つという動作をします。
    • ここで、キューへの仕事の追加と、キューからの仕事の取得は、別のスレッドで行われるため、同期制御が必要になります。
  • Queueを使うと、仕事を積む人とワーカースレッドの同期制御が内部で隠蔽されるため、外側での同期化なしにワーカースレッドを作ることができます。
    • QueueのAPIはpopとpushがあります。(他にもあるけど)
    • Queue#popで要素を取り出します。このとき、queueが空の時、呼出元のスレッドは停止(ブロック)されます。
    • Queue#pushで要素を追加します。このとき、待っているスレッドがいれば実行を再開させます。
    • 仕事をするスレッドがpushで仕事を積み、ワーカースレッドがpopで仕事を取り出すようにすれば、「仕事が積まれた場合にそれを取り出して実行。仕事がなければ、積まれるまで待つ」という動作を実現できます。

以下はQueueを使ったワーカースレッドのサンプルです。

require 'thread'

# キュー
q = Queue.new

# ワーカースレッド。
# キューから仕事を取り出して実行する。
# 仕事がなければ待つ。
workers = []
3.times { |j|
  workers << Thread.start {
    name = "thread-" << j.to_s
    loop {
      q.pop.call( name ) # キューから仕事を取り出して実行する。
      sleep rand * 0.1
    }
  }
}

# 仕事を作るスレッド。
makers = []
3.times { |j| # 3人で
  makers << Thread.start {
    5.times {|i| # 5個づつ
      q.push Proc.new {|name|  # キューに仕事を積む。
        puts name + " : " + i.to_s
      }
      sleep rand * 0.1
    }
  }
}

sleep 10 # ほんとはちゃんと待たないといけない。

実行結果です。

thread-0 : 0
thread-1 : 0
thread-2 : 0
thread-2 : 1
thread-1 : 1
thread-0 : 1
thread-2 : 2
thread-0 : 2
thread-1 : 2
thread-2 : 3
thread-2 : 3
thread-1 : 4
thread-2 : 4
thread-0 : 3
thread-1 : 4