5

ルビーでは、同時に実行されている別のスレッドからスレッドを一時停止させることは可能ですか。

以下は私がこれまでに書いたコードです。ユーザーが「スレッドの一時停止」と入力し、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
4

2 に答える 2

3

Threadオブジェクトを引数として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が呼び出されることにも注意してください。安全ではないため、あるスレッドを別のスレッドから直接停止することはできません。

于 2012-11-05T07:25:59.570 に答える
2

Rubyファイバーオブジェクトを使用して試みていることをよりよく達成できる可能性があり、実行中のシステムでより良い効率を達成できる可能性があります。

ファイバーは、Rubyで軽量の協調的並行性を実装するためのプリミティブです。基本的に、これらはスレッドのように一時停止および再開できるコードブロックを作成する手段です。主な違いは、それらがプリエンプションされることはなく、スケジューリングはVMではなくプログラマーが行う必要があることです。

MRI Rubyの現在の実装では同時実行スレッドは提供されておらず、実行できる最善の方法はグリーンスレッドプログラムであることに注意してください。以下は良い例です。

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
  # .
  # .
  # .
于 2012-11-05T05:08:01.277 に答える