2012-11-05 220 views
5

在ruby中,是否有可能导致线程从另一个并发运行的线程中暂停。Ruby暂停线程

下面是我迄今为止编写的代码。我希望用户能够键入'暂停线程'和sample500线程暂停。

#!/usr/bin/env ruby 

# Creates a new thread executes the block every intervalSec for durationSec. 
def DoEvery(thread, intervalSec, durationSec) 
    thread = Thread.new do 
     start = Time.now 

     timeTakenToComplete = 0 
     loopCounter = 0 
     while(timeTakenToComplete < durationSec && loopCounter += 1) 

      yield 

      finish = Time.now 

      timeTakenToComplete = finish - start 

      sleep(intervalSec*loopCounter - timeTakenToComplete)  
     end 
    end 
end 

# User input loop. 
exit = nil 
while(!exit) 
    userInput = gets 
    case userInput 
    when "start thread\n" 
     sample500 = Thread 
     beginTime = Time.now 
     DoEvery(sample500, 0.5, 30) {File.open('abc', 'a') {|file| file.write("a\n")}} 
    when "pause thread\n" 
     sample500.stop 
    when "resume thread" 
     sample500.run 
    when "exit\n" 
     exit = TRUE 
    end 
end 
+1

“我是Ruby的新手,只能学习几天” - 而且你已经在线程中了?这很让人佩服! –

+0

哈哈谢谢!看起来像一个非常好的语言;我喜欢整块东西和屈服! –

回答

3

将线程对象作为参数传递给DoEvery函数是没有意义的,因为您立即用Thread.new覆盖它,请检查此修改后的版本:

def DoEvery(intervalSec, durationSec) 
    thread = Thread.new do 
     start = Time.now 
     Thread.current["stop"] = false 

     timeTakenToComplete = 0 
     loopCounter = 0 
     while(timeTakenToComplete < durationSec && loopCounter += 1) 
      if Thread.current["stop"] 
       Thread.current["stop"] = false 
       puts "paused" 
       Thread.stop 
      end 

      yield 

      finish = Time.now 

      timeTakenToComplete = finish - start 

      sleep(intervalSec*loopCounter - timeTakenToComplete) 

     end 
    end 
    thread 
end 

# User input loop. 
exit = nil 
while(!exit) 
    userInput = gets 
    case userInput 
    when "start thread\n" 
     sample500 = DoEvery(0.5, 30) {File.open('abc', 'a') {|file| file.write("a\n")} } 
    when "pause thread\n" 
     sample500["stop"] = true 
    when "resume thread\n" 
     sample500.run 
    when "exit\n" 
     exit = TRUE 
    end 
end 

这里DoEvery返回新的线程对象。还要注意Thread.stop在运行线程内调用,因为它不安全,所以不能直接停止另一个线程。

+0

感谢您的回答。我喜欢你的解决方案。我在编辑中提出了一些计时问题(只是为了让其他人可能遇到的答案完成)。再次感谢! –

2

您可能能够能够更好地完成你正在使用Ruby Fiber对象,在尝试,并有可能实现在运行系统上更好的效率。

纤维是实现轻量级协作的基本要素 Ruby中的并发性。基本上他们是创建代码 可以暂停和恢复的方法,很像线程。主要的 不同之处在于它们永远不会被抢占,调度 必须由程序员而不是VM来完成。

牢记当前实现MRI的Ruby不提供任何并发运行的线程,你能做到的最好的是green threaded程序,下面是一个很好的例子:

require "fiber" 

f1 = Fiber.new { |f2| f2.resume Fiber.current; while true; puts "A"; f2.transfer; end } 
f2 = Fiber.new { |f1| f1.transfer; while true; puts "B"; f1.transfer; end } 

f1.resume f2 # => 
    # A 
    # B 
    # A 
    # B 
    # . 
    # . 
    # .