我有以下代码,其中@targets是主机名和ips的哈希,例如:
@targets = {
"www.test.com" => 1.2.3.4,
"www.test2.com" => 4.3.2.1,
"www.test2.com" => 23.24.25.23
}
代码有三个不同的“块”(块1,2,3)。
目前,每个线程都在一个主机/ IP对上工作。
我想创建三个线程,每个块一个。
因此,当block1在@targets["www.test.com"]
写入时,block2会等待。
当block1完成时,block2在@targets["www.test.com"]
写入,但block1不等待。相反,它开始在@targets["www.test2.com"]
写作。
这就像互斥锁一样,但是当我使用互斥锁时,我不能/不知道怎么告诉block1“抓住下一个目标”
require 'thread'
@targets = {
"www.test.com" => "1.2.3.4",
"www.test1.com" => "4.3.2.1",
"www.test2.com" => "23.24.25.23"
}
@vhosts={
"www.test.com"=>"web.test.com",
"www.test1.com"=>"Error",
"www.test2.com"=>"dev.test2.com"
}
@enumeration_summary={}
@targets.each do |host,ip|
@initialize = Thread.new do
#---------block1---------
puts "Host: #{host} Ip: #{ip}"
@enumeration_summary["#{host}"]={}
#---------block1 end---------
#---------block2---------
@enumeration_summary["#{host}"]={ip: ip}
#---------block2 end---------
#---------block3---------
if /Error/ === @vhosts["#{host}"]
@enumeration_summary["#{host}"][:vhosts_number_of_results]=@vhosts["#{host}"]
else
@enumeration_summary["#{host}"][:vhosts_number_of_results]=@vhosts["#{host}"].size
end
#---------block3 end---------
end #end thread
end #end of targets.each
@initialize.join
puts "===> #{@enumeration_summary}"
有时候我没有得到所有的结果,我不明白为什么。 此时,每个线程都访问@enumeration_summary哈希的不同索引。那么为什么我不能一直得到所有的结果呢? 示例输出: 示例1.一切正常:
Host: www.test.com Ip: 1.2.3.4
Host: www.test2.com Ip: 23.24.25.23Host: www.test1.com Ip: 4.3.2.1
===> {"www.test.com"=>{:ip=>"1.2.3.4", :vhosts_number_of_results=>12}, "www.test1.com"=>{:ip=>"4.3.2.1", :vhosts_number_of_results=>"Error"}, "www.test2.com"=>{:ip=>"23.24.25.23", :vhosts_number_of_results=>13}}
示例2.目标test1.com缺失
Host: www.test.com Ip: 1.2.3.4
Host: www.test2.com Ip: 23.24.25.23
Host: www.test1.com Ip: 4.3.2.1
===> {"www.test.com"=>{:ip=>"1.2.3.4", :vhosts_number_of_results=>12}, "www.test2.com"=>{:ip=>"23.24.25.23", :vhosts_number_of_results=>13}}
P.S:我只想与“线程”合作。我想避免使用任何其他gem,例如“parallel”。
提前致谢。
答案 0 :(得分:0)
这未经过测试,但它依赖于Queue文档中的示例。它将消息从block1传递到block2,从block2传递到block3,每个消息在到达时处理:
require 'thread'
queue = Queue.new
queue2 = Queue.new
producer = Thread.new do
@targets.each do |host,ip|
puts "Host: #{host} Ip: #{ip}"
@enumeration_summary["#{host}"]={}
queue << [host, ip, @enumeration_summary["#{host}"]]
end
queue = nil
end
consumer1 = Thread.new do
while value = queue.pop
value[2] = { ip: value[1] }
queue2 << value
end
queue2 << nil
end
consumer2 = Thread.new do
while value = queue2.pop
if /Error/ === @vhosts[value[0]]
value[2][:vhosts_number_of_results]=@vhosts[value[0]]
else
value[2][:vhosts_number_of_results]=@vhosts[value[0]].size
end
end
end
consumer2.join
答案 1 :(得分:0)
创建线程时,将每个线程分配给@initialize
:(覆盖变量的先前值)
@targets.each do |host, ip|
@initialize = Thread.new do
# ...
end
end
@initialize.join
最后一行只等待分配给@initialize
的线程,即最后一个线程。
为了等待所有线程,你必须将它们分配给一个数组,例如:
@threads = []
@targets.each do |host, ip|
@threads << Thread.new do
# ...
end
end
@threads.each(&:join)