2012-11-05 11 views
5

Trong ruby, có thể gây ra một luồng tạm dừng từ một luồng chạy đồng thời khác.Ruby Pause thread

Dưới đây là mã mà tôi đã viết cho đến thời điểm này. Tôi muốn người dùng có thể nhập 'tạm dừng luồng' và chuỗi mẫu500 để tạm dừng.

#!/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

"Tôi là người mới đối với Ruby; chỉ học nó trong vài ngày" - và bạn đã sẵn sàng trên luồng chưa? Ấn tượng đấy! –

+0

Haha cảm ơn! Có vẻ như một ngôn ngữ thực sự tốt đẹp; Tôi thích toàn bộ khối điều và năng suất! –

Trả lời

3

Truyền đối tượng Thread làm đối số cho hàm DoEvery không có ý nghĩa vì bạn ngay lập tức ghi đè lên bằng Thread.new, hãy xem phiên bản đã sửa đổi này:

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 

Ở đây DoEvery trả về đối tượng chuỗi mới. Cũng lưu ý rằng Thread.stop được gọi bên trong thread đang chạy, bạn không thể trực tiếp dừng một thread từ thread khác bởi vì nó không an toàn.

+0

Cảm ơn câu trả lời của bạn. Tôi thích cách giải pháp của bạn. Có một vài vấn đề thời gian với nó mà tôi đã đề xuất trong một chỉnh sửa (chỉ để làm cho câu trả lời hoàn chỉnh cho bất cứ ai khác có thể đi qua nó). Cảm ơn một lần nữa! –

2

Bạn có thể có khả năng tốt hơn để thực hiện những gì bạn đang cố gắng sử dụng Ruby Fiber đối tượng, và có khả năng đạt được hiệu quả tốt hơn trên hệ thống đang chạy.

Sợi là nguyên thủy để triển khai hợp tác trọng lượng nhẹ đồng thời trong Ruby. Về cơ bản, chúng là phương tiện tạo mã các khối có thể bị tạm dừng và tiếp tục lại, giống như các chuỗi. Sự khác biệt chính của là chúng không bao giờ được ưu tiên và việc lập lịch biểu phải do lập trình viên thực hiện chứ không phải máy ảo.

Giữ trong tâm trí thực hiện hiện tại của MRI Ruby không cung cấp bất kỳ đề chạy đồng thời và tốt nhất mà bạn có thể thực hiện là một chương trình green threaded, sau đây là một ví dụ tốt đẹp:

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 
    # . 
    # . 
    # .