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)