为什么delete_at没有删除提供的索引处的元素?

时间:2016-02-13 10:11:58

标签: ruby

我有一个WorkerJob示例,其中每个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

1 个答案:

答案 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]