为什么puts方法在线程中使用时表现得很奇怪?

解决方案:在.irbc文件中,输入: IRB.conf[:USE_READLINE] = false

我正在运行一些ruby代码:

 Thread.new do loop do a = @queue.pop puts "1" puts "2" end end 

当我在irb中运行它并且队列弹出时,它会打印“1”,但不会立即打印“2”。 在吐出“2”之前,我必须按几次输入。 这是为什么?

这是我的irb日志:

 >> Thread.new do ?> loop do ?> a = @queue.pop >> puts "1" >> puts "2" >> end >> end => # >> @queue < # >> ?> ?> ?> 2?> 

这是我得到的:

 >> require "thread" => true >> ?> @queue = Queue.new => # >> ?> Thread.new do ?> loop do ?> a = @queue.pop >> puts "1 was printed at #{Time.now.to_f}" >> puts "2 was printed at #{Time.now.to_f}" >> end >> end => # >> ?> @queue < # >> ?> ?> ?> 2 was printed at 1328144686.4642?> 

我试验了一些并发现了正在发生的事情。 您可能知道,两个Ruby线程无法同时运行; 它们只是快速来回切换。*通常,如果调用gets ,调用线程将等待输入,其他线程将继续(因为释放GIL )。 但是,在irb中,(至少在Mac OS X上)其他线程在等待输入时不会继续执行。 例:

 >> i = 0 => 0 >> Thread.new { loop { i += 1 } } => # >> i => 234866 >> i => 401271 

如果线程正在执行, i将是数百万。 (在irb外面测试。)另外,ruby使用<1%CPU。

在您的示例中,每次按Enter键时,线程都会在一瞬间执行 – 足够的时间来写出数字或换行符。 然后ruby切换回irb的线程,该线程写入提示并等待输入。

*使用JRuby,IronRuby和Rubinius 2.0,多个线程可以同时运行。

编辑:我在Windows上测试过,线程一直在那里运行。 如果你想让线程继续在Mac上运行,你可以将它保存为sirb.rb(simple irb)并使用它代替irb:

 $stdout.sync = true while true print "> " p(eval gets) end 

请注意,与irb不同,它不支持跨越多行的语句,也不支持将插入符号移动到编辑或按下Up以获取历史记录(在Mac OS X上)。 例:

 > for i in 1..10; print i ** 2, " "; end; puts 1 4 9 16 25 36 49 64 81 100 nil 

我没有得到你想要的东西。 这两个数字在我的机器上以相同的毫秒数打印。 (我在Windows机器上的1.8.7下尝试过,但仍然得到了结果)

 require "thread" @queue = Queue.new Thread.new do loop do a = @queue.pop puts "1 was printed at #{Time.now.to_f}" puts "2 was printed at #{Time.now.to_f}" end end @queue << 42 $ irb irb(main):001:0> require "thread" => true irb(main):002:0> irb(main):003:0* @queue = Queue.new => #> irb(main):004:0> irb(main):005:0* Thread.new do irb(main):006:1* loop do irb(main):007:2* a = @queue.pop irb(main):008:2> puts "1 was printed at #{Time.now.to_f}" irb(main):009:2> puts "2 was printed at #{Time.now.to_f}" irb(main):010:2> end irb(main):011:1> end => # irb(main):012:0> irb(main):013:0* @queue << 42 1 was printed at 1328144503.01272 2 was printed at 1328144503.01272 => # 

由于我无法访问OS X Lion,我无法看到它是否与Ruby on OS X Lion有关,但那是我的怀疑。