我有一个Worker
和Job
示例,其中每个Job
都有一个昂贵/慢perform
方法。
如果我Jobs
中有10个@job_table
,我想在5个批次中分别处理它们,每个都在自己的过程中。
退出5个流程(一个批次)后,我试图从Jobs
@job_table
删除jobs:
[#<Job:0x007fd2230082a8 @id=0>,
#<Job:0x007fd223008280 @id=1>,
#<Job:0x007fd223008258 @id=2>,
#<Job:0x007fd223008208 @id=3>,
#<Job:0x007fd2230081e0 @id=4>,
#<Job:0x007fd2230081b8 @id=5>,
#<Job:0x007fd223008190 @id=6>,
#<Job:0x007fd223008168 @id=7>,
#<Job:0x007fd223008140 @id=8>,
#<Job:0x007fd223008118 @id=9>]
个。{/ p>
我在我的实现中观察到意外的事情(参见下面的代码):
@job_table
这是第一批运行之前的Jobs
。我看到remove_batch_1
0-4已成功运行并退出(此处省略输出)。
所以我打电话给@job_table
并希望从jobs:
[#<Job:0x007fd223008280 @id=1>,
#<Job:0x007fd223008208 @id=3>,
#<Job:0x007fd2230081b8 @id=5>,
#<Job:0x007fd223008168 @id=7>,
#<Job:0x007fd223008118 @id=9>]
中删除0-4作业,但这正是我所观察到的:
i
我在方法中记录了delete_at
参数,它返回0-4。但看起来remove_batch_0
正在删除其他工作(0,2,4,6,8)。
我还编写了另一种删除批处理BATCH_SIZE = 5 || ENV['BATCH_SIZE']
class Job
def initialize(id)
@id = id
end
def perform
puts "Job #{@id}> Start!"
sleep 1
puts "Job #{@id}> End!"
end
end
class Worker
def initialize
@job_table = []
fill_job_table
work_job_table
end
def fill_job_table
10.times do |i|
@job_table << Job.new(i)
end
end
def work_job_table
until @job_table.empty?
puts "jobs: "
pp @job_table
work_batch
Process.waitall
remove_batch_1
end
end
def work_batch
i = 0
while (i < @job_table.length && i < BATCH_SIZE)
fork { @job_table[i].perform }
i += 1
end
end
def remove_batch_1
i = 0
while (i < @job_table.length && i < BATCH_SIZE)
@job_table.delete_at(i)
i += 1
end
end
def remove_batch_0
@job_table.slice!(0..BATCH_SIZE-1)
end
end
Worker.new
的方法,该方法使用delete_at
并按预期运行。
http://YOURSERVER.com/connectors/php/filemanager.php?mode=preview&path=%2Fuserfiles%2avatar.png&1455358031&thumbnail=true
答案 0 :(得分:2)
您在while循环中使用delete_at
。让我们看看会发生什么:
图片中有一个数组[0,1,2,3,4,5]
,您可以致电:
(1..3).each { |i| array.deleted_at(i) }
在第一次迭代中,您将从数组中删除第一个元素,在此步骤之后,数组将如下所示:[1,2,3,4,5]
在下一次迭代中,您将删除第二个元素,这将导致{{1} }。然后删除第三个:[1,3,4,5]
您可能希望改为使用Array#shift
:
[1,3,5]