Tener este código:
workers = (1..3).map do |n| Thread.new do puts print "Worker_#{n}..." sleep rand print "done (#{n})" end end.each &:join puts puts '- ready -'¿Cómo podemos obtener una salida correcta como esta (líneas actualizadas dinámicamente):
Worker_1...done (1) Worker_2...done (2) Worker_3...done (3) - ready -y no así:
Worker_1... Worker_2... Worker_3...done (3)done (1)done (2) - ready -Opción avanzada: si redirigimos la salida estándar al archivo, también debería verse bien.
Introduciría alguna clase para administrar la salida. También moverá el carro 3 líneas arriba para actualizar la salida cada vez (en el método de print ).
class StatusPrint def initialize @hash = {} end def declare_worker(name) @hash[name] = "Worker_#{name}" end def complete_worker(name) @hash[name] += "...done (#{name})" end def print(move_carriage: true) puts "\033[#{@hash.size + 1}A" if move_carriage puts @hash.values.join("\n") end def done! @done = true end def done? @done end endEntonces tu código se verá así
status_print = StatusPrint.new workers = (1..3).map do |n| Thread.new do status_print.declare_worker(n) sleep rand status_print.complete_worker(n) end end print_loop = Thread.new do status_print.print(move_carriage: false) until status_print.done? sleep 0.1 status_print.print end end workers.each &:join status_print.done! print_loop.join puts '- ready -'Además, no funcionará si desea canalizar su salida, por lo que deberá agregar alguna opción de línea de comando para deshabilitar la actualización de la salida e imprimir este texto estático:
Worker_1...done (1) Worker_2...done (2) Worker_3...done (3) - ready -Consulte también https://blog.stevenocchipinti.com/2013/06/removing-previously-printed-lines.html/ para obtener más información sobre cómo actualizar la salida.
Finalmente, he creado una gema para resolver este problema:
Gema de rubí ParaLines
Algunas muestras de uso mínimo se ven así:
require 'paralines' plines = ParaLines.new plines.add_static_line 'Gems latest versions' plines.add_empty_line gems = %w[sinatra rspec paralines rails hanami] plines.add_static_line '- Random order:' threads = gems.map do |name| Thread.new do plines << name.ljust(15, '.') res = `gem list -r #{name} -e` plines << 'v' + res[/\((.+)\)/, 1] end end sleep 0.2 plines.add_empty_line plines.add_static_line '- Sorted:' threads += gems.sort.map do |name| sline = plines.add_shared_line name.ljust(15, '.') Thread.new do res = `gem list -r #{name} -e` sline << 'v' + res[/\((.+)\)/, 1] end end threads.each &:joinEl código fuente de la muestra detallada con salida como en la animación GIF se puede encontrar en la página de la gema en GitHub .