Threads - running something in background

Hey guys,

I’ve been studying Ruby for some weeks now but when it comes to
threads, I know that I am totally unskilled.

I am trying to build a class which is able to keep updating itself every
X seconds after being initialized. In general terms it would work like
this:


class Threading_Test
attr_accessor :i
def initialize
@i = 0
@j = 0
neverstop = false

t1 = Thread.new do
        while neverstop == false do
          sleep 0.1 #here's the the problem.
          @i = @i + 1
        end
      end

t1.run

puts "I am ready and I keep updating myself. Or not..."

end
end

The problem occurs when I try to add this “sleep 0.1” into the thread
block. The thread only seems to become active when I ask for the @i
value.

I know that there might be other ways to implement that, but i think
that it would fit my code better that setting up a Cron task to do so.

Thank you all for the help.

Alex Zunega wrote:

Hey guys,

I’ve been studying Ruby for some weeks now but when it comes to
threads, I know that I am totally unskilled.

I am trying to build a class which is able to keep updating itself every
X seconds after being initialized. In general terms it would work like
this:


class Threading_Test
attr_accessor :i
def initialize
@i = 0
@j = 0
neverstop = false

t1 = Thread.new do
        while neverstop == false do
          sleep 0.1 #here's the the problem.
          @i = @i + 1
        end
      end

t1.run

puts "I am ready and I keep updating myself. Or not..."

end
end

The problem occurs when I try to add this “sleep 0.1” into the thread
block. The thread only seems to become active when I ask for the @i
value.

I’m not sure what you mean. Try this:

class Updater
attr_accessor :i

def initialize
@i = 0

Thread.new do
  loop do
    sleep(1)
    @i += 1
    puts "....#{@i}"
  end
end

end

end

upd = Updater.new

5.times do
sleep(2)
puts upd.i
end

Here is my output:
…1
1
…2
…3
3
…4
…5
5
…6
…7
7
…8
…9
9

Alex Zunega wrote:

Hey guys,

I’ve been studying Ruby for some weeks now but when it comes to
threads, I know that I am totally unskilled.

Also, you should realize that the @i in the class and the @i in the
thread are the same variable.
Therefore, things like this can happen:

class Updater
attr_accessor :i

def initialize
@i = 0

Thread.new do
  loop do
    sleep(0.3)
    @i += 1
    puts "....#{@i}"
  end
end

end

end

upd = Updater.new

3.times do
sleep(2)
puts upd.i

upd.i = 0 #<-----******
end

–output:–
…1
…2
…3
…4
…5
…6
6
…1
…2
…3
…4
…5
…6
…7
7
…1
…2
…3
…4
…5
…6
6

7stud – wrote:

Alex Zunega wrote:

Hey guys,

I’ve been studying Ruby for some weeks now but when it comes to
threads, I know that I am totally unskilled.

Also, you should realize that the @i in the class and the @i in the
thread are the same variable.
Therefore, things like this can happen:

class Updater
attr_accessor :i

def initialize
@i = 0

Thread.new do
  loop do
    sleep(0.3)
    @i += 1
    puts "....#{@i}"
  end
end

end

end

upd = Updater.new

3.times do
sleep(2)
puts upd.i

upd.i = 0 #<-----******
end

–output:–
…1
…2
…3
…4
…5
…6
6
…1
…2
…3
…4
…5
…6
…7
7
…1
…2
…3
…4
…5
…6
6

Hey 7stud,

Thanks for the very prompt answer. I couldn’t make myself clear and I’ll
try harder this time… :slight_smile:

I’ve just removed two lines from the code you genially sent me. Removing
these two lines I got the behavior I would like to have. See the code
and results below:

class Updater
attr_accessor :i

?> def initialize

@i = 0

?> Thread.new do
?> loop do
?>
?> @i += 1

?> end

end

?> end

?> end
=> nil

x.i
=> 213336

x.i
=> 237848

I just want something to time these iteration (one per second, for
example), and everytime that I insert some “sleep” method, the Updater
would “sum 1” to @i only when I try to access @i attribute.

What I expect, in other words, is to have an @i very close to the number
of seconds of the object life, just to prove that it works…

Alex Zunega wrote:

I just want something to time these iteration (one per second, for
example), and everytime that I insert some “sleep” method, the Updater
would “sum 1” to @i only when I try to access @i attribute.

What I expect, in other words, is to have an @i very close to the number
of seconds of the object life, just to prove that it works…

You aren’t making any sense. On the one hand, you say that you want @i
to tell you the number of seconds the object has been “alive”. On the
other hand, you say you only want to add 1 to @i when you try to access
@i. Which is it?

I give up.

7stud – wrote:

Alex Zunega wrote:

I just want something to time these iteration (one per second, for
example), and everytime that I insert some “sleep” method, the Updater
would “sum 1” to @i only when I try to access @i attribute.

What I expect, in other words, is to have an @i very close to the number
of seconds of the object life, just to prove that it works…

You aren’t making any sense. On the one hand, you say that you want @i
to tell you the number of seconds the object has been “alive”. On the
other hand, you say you only want to add 1 to @i when you try to access
@i. Which is it?

Actually, you’re right, I was not clear, but I meant the second one.
After initialized, 10 seconds later, when retrieving @i value I would
like to see @i as 10, meaning that for 10 times it updated itself.

7stud’s original Updater class seems to meet the requirements. Are
you trying to write a class that will perform some work and then sleep
1.0 seconds and keep a count of the number of iterations it performed?
Or are you trying to right a class that will perform some work
exactly once per second? In the first case, your work will not
generally fire once a second because the work itself will take a non
zero amount of time. The second case is trickier … maybe this would
work:

class PeriodicWorker
def initialize(period = 1.0)
@period = period
end

def run
start = Time.now.to_f
while true
yield
sleep_time = (start + @period) - Time.now.to_f
sleep(sleep_time) rescue nil # Punt if the worker took longer
than @period seconds to run
start += @period
end
end
end

worker = PeriodicWorker.new

worker.run do
puts “Time: #{Time.now.to_f}”
sleep 0.22
puts “Finished my work: #{Time.now.to_f}”
end

The only issue with this class is if the work takes longer than the
period, you are creating a spinloop that will suck up 100% of your
CPU.

-Doug Seifert