2012-11-05 265 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 
    # . 
    # . 
    # .