マルチスレットなどなど

例えば、Twitterから同時にデータを取得するような例とかを考える。自分で結構考えてみたけど、処理が同時には走らない。どの辺がおかしいのかよくわからん。。。

#!/usr/bin/ruby -Ke

require 'rubygems'
require 'thread'
require 'enumerator'
require 'pp'
require 'hpricot'
require 'mechanize'
require 'kconv'
require 'yaml'
gem 'twitter4r', '>=0.3.0'
require 'twitter'

$KCODE='e'

class Friend
  attr_accessor :name
  attr_accessor :source
  attr_accessor :agent
  attr_accessor :following
  attr_accessor :followers
  attr_accessor :favorites
  attr_accessor :update
  def initialize(twitter)
    @name = twitter[:name]
    @agent = twitter[:agent]
    @url = "http://twitter.com/"+@name

    begin
      @source = Hpricot(agent.get_file(@url))
    rescue Timeout::Error
      puts "caught Timeout::Error!"
      retry
    rescue WWW::Mechanize::ResponseCodeError => e
      case e.response_code
      when "404"
          raise "Net::HTTPNotFound!"
      when "502"
        puts "Net::HTTPBadGateway!"
        retry
      else
        raise "caught Excepcion!" + e.response_code
      end
    rescue => ex
      raise ex.message
    end
    self.set_count
    @source = ""
  rescue => ex
    raise ex.message
  end
  
  def set_count
    counter = 0
    (@source/"span.stats_count").each{ |item|
      item = item.inner_text.gsub(/,/,"")
      #1.000みたいなのの処理
      case counter
      when 0
        @following = item
      when 1
        @followers = item
      when 2
        @favorites = item
      when 3
        @update = item
      else
      end
      counter = counter+1
    }
  end
end  


friends = ["hayamiz","suztomo"].map{|name|
  puts Friend.new({
                    :name =>name,
                    :agent => WWW::Mechanize.new
                  }).name
  sleep 10
}

t = Thread.start {
  friends = ["syou6162","y_benjo"].map{|name|
    puts Friend.new({
                      :name =>name,
                      :agent => WWW::Mechanize.new
                    }).name
  }

}
t.join

追記

これだとうまく行った。

t1 = Thread.start {
  friends = ["syou6162","y_benjo","anemo","hirose30"].map{|name|
    puts Friend.new({
                      :name =>name,
                      :agent => WWW::Mechanize.new
                    }).name
  }
}

t2 = Thread.start {
  friends = ["hayamiz","suztomo","kis","hirose31"].map{|name|
    puts Friend.new({
                      :name =>name,
                      :agent => WWW::Mechanize.new
                    }).name
  }

}

t1.join
t2.join

だけど、これだとうまく行かない。この差違がよく理解できない。

Thread.start {
  friends = ["syou6162","y_benjo","anemo","hirose30"].map{|name|
    puts Friend.new({
                      :name =>name,
                      :agent => WWW::Mechanize.new
                    }).name
  }
}.join

Thread.start {
  friends = ["hayamiz","suztomo","kis","hirose31"].map{|name|
    puts Friend.new({
                      :name =>name,
                      :agent => WWW::Mechanize.new
                    }).name
  }

}.join

追追記

joinするとスレッドが終了するまでブロックされるらしい。ということでこんな感じにしたらうまくいった。

t = []
t << Thread.start {
  friends = ["syou6162","y_benjo","anemo","hirose30"].map{|name|
    puts Friend.new({
                      :name =>name,
                      :agent => WWW::Mechanize.new
                    }).name
  }
}

t << Thread.start {
  friends = ["hayamiz","suztomo","kis","hirose31"].map{|name|
    puts Friend.new({
                      :name =>name,
                      :agent => WWW::Mechanize.new
                    }).name
  }

}

t.map{|t|t.join}

追追追記

だいぶ思ってた感じのコードになった。

friends_tmp = ["syou6162","y_benjo","anemo","hirose30","hayamiz","suztomo","kis","hirose31"]

friends = []
friends_tmp.each_slice(3){|item| friends.push item}

pp friends

t = []
friends.length.times{|i|
  t << Thread.start {
    friends[i].map{|name|
      friend = Friend.new({
                        :name =>name,
                        :agent => WWW::Mechanize.new
                      })
      puts "#{friend.name} was created by thread number #{i}."
    }
  }
}

t.map{|t|t.join}

実行すると並列で3本のスレッドが走っていることが確認できる。走るからと言って大量に動かすのはやめましょう。。。

localhost% ruby easy_friend.rb
[["syou6162", "y_benjo", "anemo"],
 ["hirose30", "hayamiz", "suztomo"],
 ["kis", "hirose31"]]
hirose30 was created by thread number 1.
kis was created by thread number 2.
syou6162 was created by thread number 0.
hirose31 was created by thread number 2.
hayamiz was created by thread number 1.
y_benjo was created by thread number 0.
suztomo was created by thread number 1.
anemo was created by thread number 0.

パーフェクトRuby (PERFECT SERIES 6)

パーフェクトRuby (PERFECT SERIES 6)

  • 作者: Rubyサポーターズ,すがわらまさのり,寺田玄太郎,三村益隆,近藤宇智朗,橋立友宏,関口亮一
  • 出版社/メーカー: 技術評論社
  • 発売日: 2013/08/10
  • メディア: 大型本
  • この商品を含むブログ (22件) を見る