在Ruby中,Thread#run和Thread#wakup有什么区别?RDoc指定 scheduler 不随Thread#wakeup调用,但这意味着什么?什么时候使用 wakeup 与 run 的示例?谢谢。
编辑:
我看到Thread#wakup使线程变得可运行,但是如果在执行Thread#run之前它不会执行(无论如何都会唤醒线程),那么它有什么用呢?有人能提供一个 wakeup 做一些有意义的事情的例子吗?出于好奇心=)
py49o6xq1#
下面是一个示例来说明它的含义(代码示例来自here):
线程唤醒
thread = Thread.new do Thread.stop puts "Inside the thread block" end $ thread => #<Thread:0x100394008 sleep>
上面的输出表明新创建的线程由于stop命令而处于休眠状态。
$ thread.wakeup => #<Thread:0x100394008 run>
此输出指示线程不再休眠,可以运行。
$ thread.run Inside the thread block => #<Thread:0x1005d9930 sleep>
现在线程继续执行并打印出字符串。
$ thread.run ThreadError: killed thread
线程运行
thread = Thread.new do Thread.stop puts "Inside the thread block" end $ thread => #<Thread:0x100394008 sleep> $ thread.run Inside the thread block => #<Thread:0x1005d9930 sleep>
线程不仅唤醒,而且继续执行并打印出字符串。
yfwxisqw2#
run和wakeup之间的区别正是文档中所说的,尽管文档是关于Ruby类库的,并且没有提到MRI/YARV实现的细节,这是有意义的,因为还有其他实现,如JRuby,具有“真实的的”线程。wakeup使线程可调度(aka runnable),但不立即运行它。run也使线程可调度,但立即运行它。在MRI/YARV上,最初似乎wakeup什么也不做,但这是实现的特性。MRI/YARV有一个GVL,它一次只允许一个线程在Ruby VM中运行。线程不会被抢占,而是一直运行,直到它们放弃控制权(Thread.pass、Kernel.sleep等)或进入I/O等待,在这两种情况下,线程调度程序都会恢复当前可运行的线程之一。因此,如果您调用wakeup,然后调用Thread.pass或导致I/O wait(例如gets),您将看到另一个线程正在执行。因此,在MRI/YARV上,如果有2个线程,Thread.run实际上等于Thread.wakeup + Thread.pass。如果有更多的Thread.pass,则不一定启动被唤醒的线程,但会启动调度程序认为下一个应该运行的线程。这使得run方法成为必要,因为这是唤醒线程并使其运行的方法。就在此时此地,而不是把它留给调度程序(这对所有实现都是正确的,即使是具有“真实的”线程的实现)。
run
wakeup
Thread.pass
Kernel.sleep
gets
Thread.run
Thread.wakeup
2条答案
按热度按时间py49o6xq1#
下面是一个示例来说明它的含义(代码示例来自here):
线程唤醒
上面的输出表明新创建的线程由于stop命令而处于休眠状态。
此输出指示线程不再休眠,可以运行。
现在线程继续执行并打印出字符串。
线程运行
线程不仅唤醒,而且继续执行并打印出字符串。
yfwxisqw2#
run
和wakeup
之间的区别正是文档中所说的,尽管文档是关于Ruby类库的,并且没有提到MRI/YARV实现的细节,这是有意义的,因为还有其他实现,如JRuby,具有“真实的的”线程。wakeup
使线程可调度(aka runnable),但不立即运行它。run
也使线程可调度,但立即运行它。在MRI/YARV上,最初似乎
wakeup
什么也不做,但这是实现的特性。MRI/YARV有一个GVL,它一次只允许一个线程在Ruby VM中运行。线程不会被抢占,而是一直运行,直到它们放弃控制权(Thread.pass
、Kernel.sleep
等)或进入I/O等待,在这两种情况下,线程调度程序都会恢复当前可运行的线程之一。因此,如果您调用wakeup
,然后调用Thread.pass
或导致I/O wait(例如gets
),您将看到另一个线程正在执行。因此,在MRI/YARV上,如果有2个线程,
Thread.run
实际上等于Thread.wakeup
+Thread.pass
。如果有更多的Thread.pass
,则不一定启动被唤醒的线程,但会启动调度程序认为下一个应该运行的线程。这使得run
方法成为必要,因为这是唤醒线程并使其运行的方法。就在此时此地,而不是把它留给调度程序(这对所有实现都是正确的,即使是具有“真实的”线程的实现)。