本文介绍了为什么在线程中使用puts方法时会表现出奇怪的现象?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

SOLUTION: In .irbc file, put: IRB.conf[:USE_READLINE] = false

我正在运行一些ruby代码:

I am running some ruby code:

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

当我在irb中运行此命令并弹出队列时,它会显示"1",但不会立即显示"2".我必须按两次Enter键,然后才能吐出"2".为什么会这样?

When i run this in irb, and queue pops, it print "1", but doesn't print "2" right away. I have to press enter couple of times before it spits out "2". Why is that?

这是我的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 experimented some and found out what is happening. As you might know, two Ruby threads cannot run at the same time; they just switch back and forth quickly.* Normally, if you call gets, the calling thread will wait for input, and other threads will continue (because gets releases the GIL ). However, in irb, (at least on Mac OS X) other threads do not continue to execute while it is waiting for input. Example:

>> i = 0
=> 0
>> Thread.new { loop { i += 1 } }
=> #<Thread:0x1094d6d68 run>
>> i
=> 234866
>> i
=> 401271

如果线程正在执行,则i将以百万为单位. (在irb外部进行了测试.)此外,红宝石使用的是< 1%的CPU.

If the thread were executing, i would be in the millions. (Tested outside irb.) Plus, ruby was using < 1% CPU.

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

In your example, each time you press enter, the thread gets a split second to execute--enough time to write out a number or a newline. Then ruby switches back to irb's thread, which writes the prompt and waits on input.

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

* With JRuby, IronRuby, and Rubinius 2.0, multiple threads can run at the same time.

我在Windows上进行了测试,线程在那里继续运行.如果希望线程在Mac上继续运行,可以将其另存为sirb.rb(简单的irb),然后使用它代替irb:

I tested on Windows, and threads keep running there. If you want threads to keep running on Mac, you could save this as, say, sirb.rb (simple irb) and use it instead of irb:

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

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

Note that, unlike irb, it doesn't support a statement spanning multiple lines, nor does it support moving the caret to edit or pressing Up for history (on Mac OS X). Example:

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

这篇关于为什么在线程中使用puts方法时会表现出奇怪的现象?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

10-09 22:03