解决方案:在.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
=> #<Thread:0x10ae6d1a0 sleep>
>> @queue << "something random"
1=> #<Queue:0x10aed6420>
>>
?>
?>
?>
2?>
我得到的是:
>> require "thread"
=> true
>>
?> @queue = Queue.new
=> #<Queue:0x101bc9a60>
>>
?> 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
=> #<Thread:0x101bb8058 sleep>
>>
?> @queue << 42
1 was printed at 1328144684.33667=> #<Queue:0x101bc9a60>
>>
?>
?>
?>
2 was printed at 1328144686.4642?>
我做了一些实验,发现了正在发生的事情。正如您可能知道的,两个Ruby线程不能同时运行;它们只是快速地来回切换。*通常,如果您调用gets
,调用线程将等待输入,其他线程将继续(因为gets
释放了GIL)。然而,在irb中,(至少在Mac OS X上)其他线程在等待输入时不会继续执行。示例:
>> i = 0
=> 0
>> Thread.new { loop { i += 1 } }
=> #<Thread:0x1094d6d68 run>
>> i
=> 234866
>> i
=> 401271
如果线程正在执行,i
将以百万计。(在irb外部测试。)此外,ruby使用<1%的CPU。
在您的示例中,每次按enter键时,线程都会有一瞬间的时间执行,这足够写一个数字或一条换行符。然后ruby切换回irb的线程,该线程编写提示并等待输入。
*使用JRuby、IronRuby和Rubinius2.0,可以同时运行多个线程。
编辑:我在Windows上进行了测试,线程一直在那里运行。如果你想让线程在Mac上继续运行,你可以把它保存为sirb.rb(简单的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
我没有得到你想要的。这两个数字在同一毫秒内打印在我的机器上。(我在1.8.7下在Windows机器上尝试过,但仍然得到了结果)
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
=> #<Queue:0x1422d80 @que=[], @waiting=[], @mutex=#<Mutex:0x1422d20>>
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
=> #<Thread:0x14a4ec0 run>
irb(main):012:0>
irb(main):013:0* @queue << 42
1 was printed at 1328144503.01272
2 was printed at 1328144503.01272
=> #<Thread:0x14a4ec0 sleep>
由于我无法访问OS X Lion,我不知道这是否与OS X Lions上的Ruby有关,但这是我的怀疑。