2016-02-13 49 views
0

我有一個WorkerJob的例子,其中每個Job有一個昂貴的/緩慢的方法。爲什麼delete_at不會刪除提供的索引處的元素?

如果我在我的@job_table中有10 Jobs,我希望將它們分批處理5次,每次都在他們自己的過程中。 5個進程(一批)退出之後,我試圖從@job_tabledelete_at中刪除那些Jobs

我觀察東西在我意想不到的實施(見下面的代碼),但:

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

這是@job_table運行首批之前。我看到Jobs 0-4已經運行併成功退出(這裏省略輸出)。 所以我打電話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>] 

我登錄的方法i參數,並將其返回0-4。但它看起來像delete_at正在刪除其他工作(0,2,4,6,8)。

我還寫了另一種刪除批次remove_batch_0的方法,它使用slice!並按預期行事。

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 

回答

2

在while循環中使用delete_at。讓我們看看會發生什麼:

圖片您有一個數組[0,1,2,3,4,5]你撥打:

(1..3).each { |i| array.deleted_at(i) } 

在第一次迭代,你會從數組中刪除第一個元素,數組將這個樣子此步驟後: [1,2,3,4,5]在下一次迭代中,您將刪除第二個元素,導致[1,3,4,5]。然後刪除第三:[1,3,5]

您可能需要使用Array#shift代替:

def remove_batch_1 
    @job_table.shift(BATCH_SIZE) 
end 
+0

我無法相信我錯過了!謝謝。 – wpp

相關問題