HarlemSquirrel
HarlemSquirrel

Reputation: 10134

Inconsistent output with Ruby threads and puts

I am writing a program that will perform a number of checks and output the results via puts. I want to speed up this process using threads. However, the output includes inconsistent new lines.

How can I cleanup this output?

Ex.

> (1..99).each_with_object([]) {|i, threads| threads << Thread.new {sleep(rand 2) && puts(i)} }.each(&:join)
7
202535
36605562
7882
8959958
2826

29
433941
445258

69728063
777975



85496

22

14
24



3850



9712
9892


47

40

71
84

94
49







1
2
152187131627234218194531535759
305417
34647448
735111
66684676
838137
6133
679093
917099
3






56

32


10

6















88



86

65

Upvotes: 0

Views: 752

Answers (2)

ehoffmann
ehoffmann

Reputation: 798

Updated with the Tin Man's comment

Use print/printf or puts and provide the new-line char \n explicitly (since puts may write the new-line separately from the rest and other threads may jumping in).

(1..99).each_with_object([]) {|i, threads| threads << Thread.new {sleep(rand 2) && print("#{i}\n") } }.each(&:join)

Upvotes: 1

Max
Max

Reputation: 22325

Your threads are all sharing a resource: stdout. Whenever you have threads sharing a resource you need to make sure that you don't have more than one accessing that resource at a time, otherwise you get interference as you have observed.

Here are two approaches to solving this. First, you can change the threads to just return a value, then do all the printing afterwards:

threads = (1..99).map {|i| Thread.new { sleep(rand 2) && i } }
threads.each do |t|
  t.join
  puts t.value
end

This is a good approach if your threads all run at about the same speed since it will hang on the slowest thread (even if other faster threads have finished).

Alternatively, use a mutex to protect stdout.

mutex = Thread::Mutex.new
(1..99).map do |i|
  Thread.new { sleep(rand 2); mutex.synchronize { puts i } }
end.each(&:join)

This will let each thread run and print independently. But it's not so good if you need each thread to do a lot of printing: the more they fight over the mutex the slower your threads will get.

Upvotes: 0

Related Questions