Concurrency and Modules
Thread Result Collector
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
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}"
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 end9enddo |index|
pass 1 of 24workers = worker_count.times.map do |index0|5 Thread.new do6 base = index + 17 results[index] = base * 108 end9endworkers ← [⟨Thread A /tmp/execution/⟨tmp C⟩.rb:49 run⟩, ⟨Thread B /tmp/execution/⟨tmp C⟩.rb:49 run⟩]
pass 2 of 24workers→ [⟨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 end9endbase ← 1
pass 1 of 24workers = worker_count.times.map do |index|5 Thread.new do6 base→ 1 = index0 + 17 results[index] = base1 * 108 endbase ← 2
pass 2 of 24workers = worker_count.times.map do |index|5 Thread.new do6 base→ 2 = index1 + 17 results[index] = base2 * 108 endtotal ← 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
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 end9endworkers ← [⟨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 end9endbase ← 1
4workers = worker_count.times.map do |index|5 Thread.new do6 base→ 1 = index0 + 17 results[index] = base1 * 108 endtotal ← 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
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 end9enddo |index|
pass 1 of 34workers = worker_count.times.map do |index0|5 Thread.new do6 base = index + 17 results[index] = base * 108 end9endAll 3 passes — pass 1 is the card above pass indexworker_countworkers1 0 — — 2 1 — — 3 2 3 [⟨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⟩] base ← 1
pass 1 of 34workers = worker_count.times.map do |index|5 Thread.new do6 base→ 1 = index0 + 17 results[index] = base1 * 108 endAll 3 passes — pass 1 is the card above pass indexbase1 0 1 2 1 2 3 2 3 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