I'm experimenting with Observable Ruby class that should be capable to provide Publish/Subscribe pattern.
I wrote this code to test the behavior:
require "observer"
class Ticker ### Periodically fetch a stock price.
include Observable
attr_accessor :sleep_time
def initialize(symbol, sleep_time)
@symbol = symbol
@sleep_time = sleep_time
end
def run
last_price = nil
loop do
price = Price.fetch(@symbol)
print "#{@symbol}, Current price: #{price}\n"
if price != last_price
changed # notify observers
last_price = price
notify_observers(price)
end
sleep @sleep_time
end
end
end
class Price ### A mock class to fetch a stock price (60 - 140).
def self.fetch(symbol)
60 + rand(80)
end
end
class Notification
attr_accessor :name, :sleep_time
def initialize(ticker, name, sleep_time)
@name = name
@sleep_time = sleep_time
ticker.add_observer(self)
end
def update(price)
puts @name + ': ' + price.to_s
sleep @sleep_time
end
end
ticker = Ticker.new("MSFT", 0.5)
t1 = Thread.new { slow_notification = Notification.new(ticker, 'thread 1', 0) }
t2 = Thread.new { fast_notification = Notification.new(ticker, 'thread 2', 5) }
ticker.run
I was expecting that fast_notification sent the notification faster than slow_notification cause the sleep time for the first is one is 0 seconds and for the other one 5 seconds. In practice, they run at the same time (every 5 seconds).
答案 0 :(得分:1)
为了以异步方式处理它,线程创建应该在主循环内。我得到了这些变化的预期行为:
require "observer"
class Ticker ### Periodically fetch a stock price.
include Observable
attr_accessor :sleep_time
def initialize(symbol, sleep_time)
@symbol = symbol
@sleep_time = sleep_time
end
def run
last_price = nil
loop do
price = Price.fetch(@symbol)
#print "#{@symbol}, Current price: #{price}\n"
if price != last_price
changed # notify observers
last_price = price
Thread.new { notify_observers(price, Time.now) }
end
sleep @sleep_time
end
end
end
class Price ### A mock class to fetch a stock price (60 - 140).
def self.fetch(symbol)
7600 + rand(800)
end
end
class Notification
attr_accessor :name, :sleep_time, :working, :mutex, :counter
def initialize(ticker, name, sleep_time)
@name = name
@sleep_time = sleep_time
@working = false
@mutex = Mutex.new
@counter = 0
ticker.add_observer(self)
end
def do_something(price)
puts @name + ': ' + price.to_s
sleep @sleep_time
end
def update(price, time)
@mutex.synchronize{
do_something(price)
}
end
end
ticker = Ticker.new("MSFT", 0.5)
Notification.new(ticker, 'Fast notification', 0)
Notification.new(ticker, 'Slow notification', 5)
ticker.run
答案 1 :(得分:0)
我认为你应该刷新缓冲区。尝试在打印后添加STDOUT.flush
。
def run
last_price = nil
loop do
price = Price.fetch(@symbol)
print "#{@symbol}, Current price: #{price}\n"
STDOUT.flush
if price != last_price
changed # notify observers
last_price = price
notify_observers(price)
end
sleep @sleep_time
end
end