我希望能够调用一个在单独的线程上重复 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 多线程的理解很薄弱,任何人都能够理解我在这里想要达到的目的并推动我朝着正确的方向前进?