我希望能够在一个单独的线程上调用一个重复x次的方法,该线程每隔几分钟就会向控制台发送“仍在运行”等消息,而我可以自由地调用其他执行相同操作的方法
这在我的测试环境中有效,并且所有内容都通过rspec检出 - 但是当我将代码移动到gem并从另一个脚本调用它时,似乎代码在其他线程中工作,但字符串永远不会发送到我的控制台(或我可以告诉的任何地方)。
我将把下面代码的重要部分放在下面,但为了更好地理解,重要的是要知道:
以下是代码:
require "trade_watcher/version"
require "market_beat"
module TradeWatcher
def self.check_stock_every_x_seconds_for_value(symbol, seconds, value)
t1 = Thread.new{(self.checker(symbol, seconds, value))}
end
private
def self.checker(symbol, seconds, value)
stop_time = get_stop_time
pp stop_time
until is_stock_at_or_above_value(symbol, value) || Time.now >= stop_time
pp "#{Time.now} #{symbol} has not yet met your target of #{value}."
sleep(seconds)
end
if Time.now >= stop_time
out_of_time(symbol, value)
else
reached_target(symbol, value)
end
end
def self.get_stop_time
Time.now + 3600 # an hour from Time.now
end
def self.reached_target(symbol, value)
pp "#{Time.now} #{symbol} has met or exceeded your target of #{value}."
end
def self.out_of_time(symbol, value)
pp "#{Time.now} The monitoring of #{symbol} with a target of #{value} has expired due to the time limit of 1 hour being rached."
end
def self.last_trade(symbol)
MarketBeat.last_trade_real_time symbol
end
def self.is_stock_at_or_above_value(symbol, value)
last_trade(symbol).to_f >= value
end
end
以下是测试(全部通过):
require 'spec_helper'
describe "TradeWatcher" do
context "when comparing quotes to targets values" do
it "can report true if a quote is above a target value" do
TradeWatcher.stub!(:last_trade).and_return(901)
TradeWatcher.is_stock_at_or_above_value(:AAPL, 900).should == true
end
it "can report false if a quote is below a target value" do
TradeWatcher.stub!(:last_trade).and_return(901)
TradeWatcher.is_stock_at_or_above_value(:AAPL, 1000).should == false
end
end
it "checks stock value multiple times while stock is not at or above the target value" do
TradeWatcher.stub!(:last_trade).and_return(200)
TradeWatcher.should_receive(:is_stock_at_or_above_value).at_least(2).times
TradeWatcher.check_stock_every_x_seconds_for_value(:AAPL, 1, 400.01)
sleep(2)
end
it "triggers target_value_reahed when the stock has met or surpassed the target value" do
TradeWatcher.stub!(:last_trade).and_return(200)
TradeWatcher.should_receive(:reached_target).exactly(1).times
TradeWatcher.check_stock_every_x_seconds_for_value(:AAPL, 1, 100.01)
sleep(2)
end
it "returns a 'time limit reached' message once a stock has been monitored for the maximum of 1 hour" do
TradeWatcher.stub!(:last_trade).and_return(200)
TradeWatcher.stub!(:get_stop_time).and_return(Time.now - 3700)
TradeWatcher.check_stock_every_x_seconds_for_value(:AAPL, 1, 100.01)
TradeWatcher.should_receive(:out_of_time).exactly(1).times
sleep(2)
end
end
这是一个非常简单的脚本(按照我的理解)应该打印“{Time.now} AAPL尚未达到800.54的目标。”该方法仍在运行的每1秒钟至少应该可见20秒(我在rspec中使用sleep进行测试,并且能够看到打印到控制台的字符串):
require 'trade_watcher'
TradeWatcher.check_stock_every_x_seconds_for_value(:AAPL, 1, 800.54)
sleep (20)
但是我没有输出 - 虽然程序确实等了20秒才完成。如果我添加其他行打印到控制台,它们工作得很好,但是我的TradeWatcher方法调用触发的线程中的任何内容都没有实际工作。
简而言之,我不理解如何让线程相互通信 - 或者如何将它们彼此同步(我不认为thread.join在这里是合适的,因为它会让主线程挂起如果我选择在将来一次发送一个方法,则无法接受另一个方法调用。 我对Ruby多线程的理解很弱,任何人都能够理解我想要在这里得到什么并向我推进正确的方向?
答案 0 :(得分:0)
当你去打印时,看起来像是没有用ruby加载pp函数。添加:
require 'pp'
到trade_watcher.rb的顶部我能够得到你期待的输出。您可能还想考虑添加:
$stdout.sync = $stderr.sync = true
到你的二进制/可执行脚本,这样你的输出就不会被IO类内部缓冲,而是直接传递给操作系统。