require 'thread' class OrangeTree GROWTH_PER_YEAR = 1 AGE_TO_START_PRODUCING_ORANGE = 3 AGE_TO_DIE = 7 ORANGE_COUNT_RELATIVE_TO_AGE = 50 def initialize @height = 0 @age = 0 @orange_count = 0 end def height return @height end def age return @age end def count_the_oranges return @orange_count end def one_year_passes @age += 1 @height += GROWTH_PER_YEAR @orange_count = Math.rand(@age..AGE_TO_DIE) * Math.log(@age) * ORANGE_COUNT_RELATIVE_TO_AGE end def pick_an_orange if (@age == AGE_TO_DIE) puts "Sorry, the Orange tree is dead" elsif (@orange_count > 0) @orange_count -= 1 puts "The Orange is delicious" else puts "Sorry, no Oranges to pick" end end end class Worker def initialize(mutex, cv, orange_tree) @mutex = mutex @cv = cv @orange_tree = orange_tree end def do_some_work Thread.new do until (@orange_tree.age == OrangeTree.AGE_TO_DIE) @mutex.synchronize do sleep_time = rand(0..5) puts "Orange picker going to sleep for #{sleep_time}" sleep(sleep_time) puts "Orange picker woke up after sleeping for #{sleep_time}" @orange_tree.pick_an_orange puts "Orange picker waiting patiently..." @cv.wait(@mutex) end end end Thread.new do until (@orange_tree.age == OrangeTree.AGE_TO_DIE) @mutex.synchronize do sleep_time = rand(0..5) puts "Age increaser going to sleep for #{sleep_time}" sleep(sleep_time) puts "Age increaser woke up after sleeping for #{sleep_time}" @orange_tree.one_year_passes puts "Age increaser increased the age" @cv.signal end end end end Worker.new(Mutex.new, ConditionVariable.new, OrangeTree.new).do_some_work until (@orange_tree.age == OrangeTree.AGE_TO_DIE) # wait for the Threads to finish end end