Worker threads can compute independent results while the main thread waits and combines them in a predictable order.

thread results Store each worker result in a fixed array slot, then join the workers before reading the final collection.

Thread Result Collector

worker_count
thread_result_collector.rb
Replay: real traced execution (multi-file project)
worker_count = 2
results = Array.new(worker_count)

workers = worker_count.times.map do |index|
  Thread.new do
    base = index + 1
    results[index] = base * 10
  end
end

workers.each(&:join)

total = results.sum
puts "workers=#{worker_count}"
puts "results=#{results.join(",")}"
puts "total=#{total}"
worker_count = 1
results = Array.new(worker_count)

workers = worker_count.times.map do |index|
  Thread.new do
    base = index + 1
    results[index] = base * 10
  end
end

workers.each(&:join)

total = results.sum
puts "workers=#{worker_count}"
puts "results=#{results.join(",")}"
puts "total=#{total}"
worker_count = 3
results = Array.new(worker_count)

workers = worker_count.times.map do |index|
  Thread.new do
    base = index + 1
    results[index] = base * 10
  end
end

workers.each(&:join)

total = results.sum
puts "workers=#{worker_count}"
puts "results=#{results.join(",")}"
puts "total=#{total}"
  1. worker_count ← 2, results ← [nil, nil]

    1worker_count→ 2 = 2  #@worker_count=1, 32results→ [nil, nil] = Array.new(worker_count2)34workers = worker_count2.times.map do |index|5  Thread.new do6    base = index + 17    results[index] = base * 108  end9end
  2. do |index|

    pass 1 of 2
    4workers = worker_count.times.map do |index0|5  Thread.new do6    base = index + 17    results[index] = base * 108  end9end
  3. workers ← [⟨Thread A /tmp/execution/⟨tmp C⟩.rb:49 run⟩, ⟨Thread B /tmp/execution/⟨tmp C⟩.rb:49 run⟩]

    pass 2 of 2
    4workers→ [⟨Thread A /tmp/execution/⟨tmp C⟩.rb:49 run⟩, ⟨Thread B /tmp/execution/⟨tmp C⟩.rb:49 run⟩] = worker_count2.times.map do |index1|5  Thread.new do6    base = index + 17    results[index] = base * 108  end9end
  4. base ← 1

    pass 1 of 2
    4workers = worker_count.times.map do |index|5  Thread.new do6    base→ 1 = index0 + 17    results[index] = base1 * 108  end
  5. base ← 2

    pass 2 of 2
    4workers = worker_count.times.map do |index|5  Thread.new do6    base→ 2 = index1 + 17    results[index] = base2 * 108  end
  6. total ← 30

    11workers.each(&:join)[⟨Thread A /tmp/execution/⟨tmp C⟩.rb:49 dead⟩, ⟨Thread B /tmp/execution/⟨tmp C⟩.rb:49 dead⟩]1213total→ 30 = results.sum3014puts "workers=#{worker_count2}"15puts "results=#{results.join(",")10,20}"16puts "total=#{total30}"
    outputworkers=2
    results=10,20
    total=30
  1. worker_count ← 1, results ← [nil]

    1worker_count→ 1 = 12results→ [nil] = Array.new(worker_count1)34workers = worker_count1.times.map do |index|5  Thread.new do6    base = index + 17    results[index] = base * 108  end9end
  2. workers ← [⟨Thread A /tmp/execution/⟨tmp B⟩.rb:49 run⟩]

    4workers→ [⟨Thread A /tmp/execution/⟨tmp B⟩.rb:49 run⟩] = worker_count1.times.map do |index0|5  Thread.new do6    base = index + 17    results[index] = base * 108  end9end
  3. base ← 1

    4workers = worker_count.times.map do |index|5  Thread.new do6    base→ 1 = index0 + 17    results[index] = base1 * 108  end
  4. total ← 10

    11workers.each(&:join)[⟨Thread A /tmp/execution/⟨tmp B⟩.rb:49 dead⟩]1213total→ 10 = results.sum1014puts "workers=#{worker_count1}"15puts "results=#{results.join(",")10}"16puts "total=#{total10}"
    outputworkers=1
    results=10
    total=10
  1. worker_count ← 3, results ← [nil, nil, nil]

    1worker_count→ 3 = 32results→ [nil, nil, nil] = Array.new(worker_count3)34workers = worker_count3.times.map do |index|5  Thread.new do6    base = index + 17    results[index] = base * 108  end9end
  2. do |index|

    pass 1 of 3
    4workers = worker_count.times.map do |index0|5  Thread.new do6    base = index + 17    results[index] = base * 108  end9end
    All 3 passes — pass 1 is the card above
    passindexworker_countworkers
    10
    21
    323[⟨Thread A /tmp/execution/⟨tmp D⟩.rb:49 run⟩, ⟨Thread B /tmp/execution/⟨tmp D⟩.rb:49 run⟩, ⟨Thread C /tmp/execution/⟨tmp D⟩.rb:49 run⟩]
  3. base ← 1

    pass 1 of 3
    4workers = worker_count.times.map do |index|5  Thread.new do6    base→ 1 = index0 + 17    results[index] = base1 * 108  end
    All 3 passes — pass 1 is the card above
    passindexbase
    101
    212
    323
  4. total ← 60

    11workers.each(&:join)[⟨Thread A /tmp/execution/⟨tmp D⟩.rb:49 dead⟩, ⟨Thread B /tmp/execution/⟨tmp D⟩.rb:49 dead⟩, ⟨Thread C /tmp/execution/⟨tmp D⟩.rb:49 dead⟩]1213total→ 60 = results.sum6014puts "workers=#{worker_count3}"15puts "results=#{results.join(",")10,20,30}"16puts "total=#{total60}"
    outputworkers=3
    results=10,20,30
    total=60