Thread Priorities

So far, I’ve given Ruby total freedom in slicing up the time between threads in any way it wants. But sometimes one thread is more important than the others. For example, if you are writing a file-copying program with one thread to do the actual copying and another thread to display the progress bar, it would make sense to give the file-copying thread most of the time.

Note

There may be times when the currently executing thread specifically wants to give execution time to other threads. This is done by calling the Thread.pass method. However, this may not produce quite the results you expect. The pass method is discussed in more detail in Digging Deeper in Digging Deeper.

Ruby lets you assign integer values to indicate the priority of each thread. In theory, threads with higher priorities are allocated more execution time than threads with lower priorities. In practice, things aren’t that simple since other factors (such as the order in which threads are run) may affect the amount of time given to each thread. Moreover, in very short programs, the effects of varying the priorities may be impossible to determine. The little words-and-numbers thread example you’ve used up to now is far too short to show any clear differences. So, let’s take a look at a slightly more labor-intensive program—one that runs three threads, each of which calls a method fifty times in order to compute the factorial of 50. For our purposes, it’s not important to understand how the code calculates factorials. Bear in mind, though, that it uses the shorthand (ternary operator) if..else notation (< Test Condition > ? <if true do this> : <else do this>) explained in Chapter 6:

threads4.rb

def fac(n)
    n == 1 ? 1 : n * fac(n-1)
end

t1 = Thread.new{
    0.upto(50) {fac(50); print( "t1
" )}
}

t2 = Thread.new{
    0.upto(50) {fac(50); print( "t2
" )}
}

t3 = Thread.new{
    0.upto(50) {fac(50); print( "t3
" )}
}

You can now set specific priorities for each thread:

t1.priority = 0
t2.priority = 0
t3.priority = 0

In this case, the priorities are the same for each thread, so, in principle, no thread will be given the biggest slice of the action, and the results from all three threads should appear in the usual jumble. This is indeed the case in Ruby 1.8, but be aware that thread priorities may not always produce the expected results in some versions of Ruby 1.9.

Now, in threads4.rb try changing the priority of t3:

t3.priority = 1

This time when you run the code, t3 will (at least in Ruby 1.8) grab most of the time and execute (mostly) before the other threads. The other threads may get a look in at the outset because they are created with equal priorities and the priority is changed only after they have started running. When t3 has finished, t1 and t2 should share the time more or less equally.

So, let’s suppose you want t1 and t2 to run first, sharing time more or less equally and running t3 only after those two threads have finished. Here’s my first attempt; you may want to try it yourself:

t1.priority = 2
t2.priority = 2
t3.priority = 1

Hmm, the end result is not what I wanted! It seems that the threads are run in sequence with no time-slicing at all! Okay, just for the heck of it, let’s try some negative numbers:

t1.priority = −1
t2.priority = −1
t3.priority = −2

Hurrah! That’s more like it. This time (at least in Ruby 1.8), t1 and t2 run concurrently though you may also see t3 executing briefly before the thread priorities are set; then t3 runs. So, why do negative values work but positive values don’t?

There is nothing special about negative values per se. However, you need to bear in mind that every process has at least one thread running—the main thread—and this too has a priority. Its priority happens to be 0.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
3.17.164.34