For example, we have ruby-code that execs some I/O operations in a row (for instance, it runs 3 queries to database).
class A
def initialize
@data = {}
end
# Run class and collect data to the hash
def call
do_1
do_2
do_3
@data
end
private
def do_1
@data['1'] = exec_some_io
end
def do_2
@data['2'] = exec_some_io
end
def do_3
@data['3'] = exec_some_io
end
def exec_some_io
time = (0.1..0.2).step(0.01).to_a.sample
sleep(time)
[1,2,3].sample
end
end
puts A.new.call
In order to optimise code and reduce execution time, we can rewrite it and use Thread.
class A
def call
[
Thread.new { do_1 },
Thread.new { do_2 },
Thread.new { do_3 },
].map(&:join)
@data
end
private
def do_1
@data['1'] = exec_some_io
end
def do_2
@data['2'] = exec_some_io
end
def do_3
@data['3'] = exec_some_io
end
end
Please, don't write the code like that. Firstly, methods do_1
, do_2
, do_3
know a lot of information about the data structure. Secondly, as we are using threads, we don't control context. It's dangerous and can produce errors in our application. In order to fix it, we have to use value method. It's easy to rewrite:
class A
def call
@data = {
'1' => Thread.new { do_1 },
'2' => Thread.new { do_2 },
'3' => Thread.new { do_3 },
}.transform_values(&:value)
@data
end
private
def do_1
exec_some_io
end
def do_2
exec_some_io
end
def do_3
exec_some_io
end
end
Now, our ruby-code is thread-safe.
Top comments (0)