# Doing Two Things at Once with Threads

#### Problem

You want your program to run two or more pieces of code in parallel.

#### Solution

Create a new thread by passing a code block into THRead.new. That block will run simultaneously with any code you write after the call to THRead.new.

The following code features two competing threads. One continually decrements a variable by one, while the main programs thread busily incrementing the same variable by three. The decrementing thread starts its work earlier, but the incrementing thread always wins in the end, because it increments the counter by a larger number:

```	x = 0
while x < 5
x -= 1
puts "DEC: I decremented x to #{x}
"
end
puts "DEC: x is too high; I give up!
"
end

while x < 5
x += 3
puts "INC: I incremented x to #{x}
"
end
# DEC: I decremented x to -1
# DEC: I decremented x to -2
# DEC: I decremented x to -3
# DEC: I decremented x to -4
# INC: I incremented x to -1
# DEC: I decremented x to -2
# INC: I incremented x to 1
# DEC: I decremented x to 0
# INC: I incremented x to 3
# DEC: I decremented x to 2
# INC: I incremented x to 5
# DEC: x is too high; I give up!

x # => 5
```

#### Discussion

A Ruby process starts out running only one thread: the main thread. When you call Thread#new, Ruby spawns another thread and starts running it alongside the main thread. The operating system divides CPU time among all the running processes, and the Ruby interpreter further divides its alotted CPU time among all of its threads.

The block you pass into THRead.new is a closure (see Recipe 7.4), so it has access to all the variables that were in scope at the time you instantiated the thread. This means that threads can share variables; as a result, you don need complex communication schemes the way you do to communicate between processes. However, it also means that your threads can step on each others toes unless you e careful to synchronize any shared objects. In the example above, the threads were designed to step on each others toes, providing head-to-head competition, but usually you don want that.

This code spawns a subthread to count to one million. Without the call to Thread#join, the counter only gets up to a couple hundred thousand before the process exits:

```	#!/usr/bin/ruby -w
counter = 0
1.upto(1000000) { counter += 1; }
end

puts "The counter was able to count up to #{counter}."
The counter was able to count up to 1000000.

The counter was able to count up to 172315.
```

You can get a list of the currently active thread objects with Thread.list:

```	Thread.new { sleep 10 }
Thread.new { x = 0; 10000000.times { x += 1 } }
# => [#, #,
# #, #]
```

Here, the two running threads are the main irb thread and the thread running the counter loop. The two sleeping threads are the ones currently running sleep calls.

Ruby Cookbook (Cookbooks (OReilly))
ISBN: 0596523696
EAN: 2147483647
Year: N/A
Pages: 399

Similar book on Amazon