awojo
awojo

Reputation: 967

Ruby multithreading questions

I've started looking into multi-threading in Ruby.

So basically, I want to create a few threads, and have them all execute, but not display any of the output until the thread has successfully completed.

Example:

#!/usr/bin/env ruby

t1 = Thread.new {
puts "Hello_1"
sleep(5)
puts "Hello_1 after 5 seconds of  sleep"
}

t2 = Thread.new {
puts "Hello_2"
sleep(5)
puts "Hello_2 after 5 seconds of  sleep"
}

t1.join
t2.join

puts "Hello_3"
sleep(5)
puts "Hello_3 after 5 seconds of  sleep"

The first Hello_1 / Hello_2 execute immediately. I wouldn't want any of the output to show until the thread has successfully completed.

Upvotes: 3

Views: 2139

Answers (2)

grillp
grillp

Reputation: 1273

Because puts prints to a single output stream (sysout) you can't use it if you want to capture the output each thread.

You will have to use separate buffered stream for each thread, write to that in each thread, and then dump them to sysout when the thread terminates to see the output.

Here is an example of a thread:

t = Thread.new() do
  io = StringIO.new
  io << "mary"
  io.puts "fred"
  io.puts "fred"
  puts io.string
end

You will have to pass io to every method in the thread.

or have a look at this for creating a module that redirects stdout for a thread.

But in each thread that your start wrap your code with:

Thread.start do
  # capture the STDOUT by storing a StringIO in the thread space
  Thread.current[:stdout] = StringIO.new
  # Do your stuff.. print using puts
  puts 'redirected to StringIO'
  # print everything before we exit
  STDIO.puts Thread.current[:stdout].string
end.join

Upvotes: 6

pguardiario
pguardiario

Reputation: 54984

You can share a buffer but you should 'synchronize' access to it:

buffer = ""
lock = Mutex.new

t1 = Thread.new {
lock.synchronize{buffer << "Hello_1\n"}
sleep(5)
lock.synchronize{buffer << "Hello_1 after 5 seconds of  sleep\n"}
}

t2 = Thread.new {
lock.synchronize{buffer << "Hello_2\n"}
sleep(5)
lock.synchronize{buffer << "Hello_2 after 5 seconds of  sleep\n"}
}

t1.join
t2.join

puts buffer

Upvotes: 0

Related Questions