我正在尝试从网站上删除一些信息,而我之前从未使用过线程。我把这个测试混在一起模仿我正在尝试做的事情:
require 'thread'
mutex = Mutex.new
mut = Mutex.new
hash = {}
n = 0
a = []
b = []
# x = 0
10.times do |i|
a << Thread.new(i) do |top_index|
mutex.synchronize do
hash[top_index] = []
sleep 0.2
100.times do |sub_index|
b << Thread.new(top_index, sub_index, hash) do |t, s, my_hash|
mut.synchronize do
r = s
sleep 0.2
my_hash[t].push(s)
end
end
end
b.each {|y| y.join }
puts "sub: #{top_index} - #{hash[top_index].length}"
puts hash[top_index]
end
end
end
a.each {|q| q.join }
hash.each { |key, value| n += value.length }
puts "Final Tally - #{n}"
sleep
代表某些RestClient get
请求,以及代表我从网站上抓取的某些信息的排序和push
的数字。但是当查看输入所有内容的顺序时,我注意到跨数组的模式,所以我想知道在一个线程中何时分配r
它会影响其在另一个线程中的值。但这没有意义,因为这会严重限制其对并发请求的有用性。
另外,我认为既然一切都是并发的(或者就像它的并发一样)它应该在几秒钟内返回睡眠定时器,但它实际上需要一段时间。
我刚试过它,它实际上比没有线程的时间更长?
螺纹总时间:204.04028
正常总数:203.133638
所以,现在我很困惑。
答案 0 :(得分:1)
我不知道你注意到了什么“模式”;但一般来说,您在示例中使用Thread
初始值设定项的方式应该可以正常运行。
我刚试过它,它实际上比没有线程的时间更长?
这是因为你正在用这些线程同步所有你正在做的工作。所以没有并发性。因此,单线程解决方案优于“多线程”解决方案是有道理的,因为后者只是执行与前者相同的所有工作(以相同的顺序),并产生额外的产生线程的开销(并制作它们)等待)。
您不需要同步这些操作。 Ruby解释器有一个global interpreter lock,可以防止开发人员在低级语言中遇到大多数竞争条件。您希望使用 以下是您的示例(没有同步)的精简版本,可以正常工作:Mutex
的主要方案是,在外部 Ruby地区(例如,某些较低级别的系统操作)可能需要同步。< / p>
require 'thread'
hash = {}
outer_threads = []
inner_threads = []
10.times do |i|
outer_threads << Thread.new(i) do |top_index|
hash[top_index] = []
sleep 0.2
20.times do |sub_index|
inner_threads << Thread.new(top_index, sub_index, hash[top_index]) do |t, s, arr|
sleep 0.2
arr.push(s + 1)
end
end
inner_threads.each(&:join)
end
end
outer_threads.each(&:join)
# Verify that the hash is populated with arrays comprising the numbers 1 to 20,
# as we would expect.
hash.each do |key, value|
puts "#{key}: #{value.sort.join(', ')}"
end