queue に入れたデータを multithread で処理して結果を results へ入れる例
require 'thread'
queue = Queue.new
5.times {|i| queue.push i}
thread_n = 3 # つくられるスレッドの数
mutex = Mutex.new
results = {}
threads = []
thread_n.times do
queue.push(nil)
t = Thread.new do
while x = queue.pop
sleep(1)
mutex.synchronize do
results[x] = x * x
end
end
end
threads.push(t)
end
threads.each {|t| t.join}
puts results
ポイントは、
queue
にnil
を入れておくことで、while
を抜けるようにするnil
入れずにqueue
が空になるとthread
は停止するので、join
のところでコケる。その場合はまた別の待ち方が必要while
でqueue.pop
のかわりにqueue.empty?
をしてしまうと、その後pop
するまでの間に別の thread がpop
してしまう恐れがあるのでダメ
- スレッドの外へ渡す共有データを操作する処理は、
mutex.synchronize
へブロックを渡して実行する- 同時に更新してしまうことを避けるため
なお、処理途中で queue に追加するような場合は上のコードだと途中で止まっちゃうのでダメ。
ssh ごしに実行したコマンドの結果のとりかたについて
小さい場合は
x = ssh.exec(cmd)
というのでよいけど、x には全データが入るので、大きい場合にはメモリが一杯になる。
以下のようにすれば、適当な大きさごとに処理できる。
ssh.exec! "grep something /some/files" do |ch, stream, data|
if stream == :stderr
puts "ERROR: #{data}"
else
puts data
end
end
検証で "あ" をたくさん書いたファイルを cat してみた。なお、utf8 で "あ" は次のとおり e3 81 82 の3バイト。
> puts 'あ'.bytes.map{|x| x.to_s(16)}.join(' ')
e3 81 82
> ssh.exec!("cat /tmp/test.txt") {|ch, stream, data|
puts '---begin---';
puts data.bytesize;
puts 'head: ' + data.bytes.map{|x| x.to_s(16)}[0..5].join(' ');
puts 'tail: ' + data.bytes.map{|x| x.to_s(16)}[-5..-1].join(' ');
puts 'valid_encoding?: ' + data.valid_encoding?.to_s;
puts '---end---'
}
---begin---
16384
head: e3 81 82 e3 81 82
tail: 82 e3 81 82 e3
valid_encoding?: true
---end---
---begin---
16384
head: 81 82 e3 81 82 e3
tail: e3 81 82 e3 81
valid_encoding?: true
---end---
---begin---
16384
head: 82 e3 81 82 e3 81
tail: 81 82 e3 81 82
valid_encoding?: true
---end---
---begin---
9211
head: e3 81 82 e3 81 82
tail: 82 e3 81 82 a
valid_encoding?: true
---end---
というふうに、"あ" の途中で区切られて送られている。data は String のくせに!でも valid_encoding?
で true
が返るのがはぜだろう??
sort() and sort_by() are not stable. You can use stable sort as following code.
i = 0
list.sort_by {|x| [x, i += 1]}
http://docs.ruby-lang.org/ja/1.9.3/method/Enumerable/i/sort_by.html
def debug
yield
rescue => ex
puts "---class---\n#{ex.class}\n---message---\n#{ex.message}\n---backtrace---\n#{ex.backtrace.join("\n")}\n----------"
end
debug {
# テストしたいコード
}
的な。
logger = Object.new
def logger.info(*args); end
def logger.debug(*args); end
def logger.warn(*args); end
def logger.error(*args); end