jruby 并发池线程在组合结果时混淆

问题描述

一个索引为 [[0,n_0],[1,n_1],...,[n,n_n]] 的数组。对于每个 n_i,都会调用一个函数。在每个线程终止后,有必要按第一个组件对线程的结果进行重新排序。就我能找到的方法而言,我通过询问索引是否是例如索引来组织索引是硬编码的。 0,然后为硬编码索引 0 单独启动代码。到目前为止,这是一种可行的方法(即使代码看起来好像有人不了解循环的用途)。

rest = []
tpl.each do |idx,vn|
    if idx == 0
        pool.post do
            res = funk(vn)
p ['idx 0: ',res]
            rest += [[0,res]]
        end#pool.post
    elsif idx == 1
        pool.post do
            res = funk(vn)
p ['idx 1: ',res]
            rest += [[1,res]]
        end#pool.post
end;end

但是现在有一个奇怪的行为: 索引 0 和 1 计算准确,但是当 1 的结果在后一行添加时,前一个函数的结果会被添加(再次)。

["idx 1: ",[4]]
["idx 0: ",[16900]]
rest: [[0,[16900]],[16900],...]

情况并非总是如此,因此这取决于结果出现的顺序。 如果例如索引0的计算在索引1的计算完成后,则idx 1缺失,或者错误。但也出现了其他混淆结果的情况:idx 0 在 idx 1 之前,但 idx 0 的结果是 idx 1 的结果。

看起来线程并没有真正分开。可以强制执行吗,或者有更聪明的方法来保持 indeces?

解决方法

我发现一种选择是同步线程,但这会使算法再次变慢,因此更好的解决方案是:

结果不会混淆,如果其余元组已经具有区分传入结果的结构:

rest = [[],[]]
tpl.each do |idx,vn|
    if idx == 0
        pool.post do
            res = funk(vn)
p ['idx 0: ',res]
            rest[0] << [0,res]
        end#pool.post
    elsif idx == 1
        pool.post do
            res = funk(vn)
p ['idx 1: ',res]
            rest[1] << [1,res]
        end#pool.post
end;end