Thread means lightweight sub-process. It is a separate path of execution. In Ruby, different parts of a program can run at the same time by either splitting tasks within a program using multiple threading or splitting tasks between different programs using multiple process.
Threads are the Ruby implementation for a concurrent programming model.
Ruby Multithreading
A normal program has single thread of execution. All the statements in the program are executed sequentially.
A multi thread program has more than one thread of execution in it. It uses less memory space and share same address space. Multithreading is used to perform more than one task at once.
A new thread is created using thread.new call. It is different from the main thread’s execution.
Thread Initialization
To create a new thread Ruby provides three keywords namely, ::new, ::start and ::fork.
To start a new thread, associate a block of code with a call to Thread.new, Thread.start or Thread.fork. Thread will be created. The new thread exits when the block exit.
Syntax:
# Original thread runs
Thread.new {
# New thread is created.
}
# Original thread runs
Thread Termination
There are different ways to terminate a thread in Ruby. To exit a given thread, class ::kill is used.
Syntax:
thr = Thread.new { ... }
Thread.kill(thr)
Ruby Thread Example
#!/usr/bin/ruby
th = Thread.new do #Here we start a new thread
Thread.current['counter']=0
5.times do |i| #loop starts and increases i each time
Thread.current['counter']=i
sleep 1
end
return nil
end
while th['counter'].to_i < 4 do
=begin
th is the long running thread
and we can access the same variable
from inside the thread here
=end
puts "Counter is #{th['counter']}"
sleep 0.5
end
puts "Long running process finished!"
Output:
ADVERTISEMENT
Thread Lifecycle
Once a thread is created, there is no need to start it. It automatically runs when it gets proper CPU resources. The last expression in a block is the value of the thread. If thread has run completely, value method returns the thread value, otherwise value method blocks it and returns when the thread has completed. A number of methods are defined by thread class while running query and manipulate the thread.
By calling a thread’s Thread.join method, you can wait for a particular thread to finish.
Thread Exception Handling
Threads may have some exceptions in them. If exception arises in any thread other than main thread, it depends upon abort_on_exception. By default this option is always false. It means unhandled exception will silently terminate the thread. This can be changed by setting either abort_on_exception = true or $DEBUG to true.
To handle exception, you can use class method ::handle_interrupt. It will handle exceptions asynchronously with threads.
Thread Variables and Scope
Threads are created with blocks. A local variable created within a block is accessible to only thread in which this block is present.
Ruby thread class allows thread-local variables to be created and accessed by name. Thread object is treated like a hash, writing elements using []= and reading them back using [].
Thread Scheduling
Ruby supports scheduling threads by using ::stop and ::pass methods in a program.
The ::stop class method put the current running thread to sleep and schedule the execution of another thread. Once the thread is asleep, instance method wakeup is used to mark thread as eligible for scheduling.
The ::pass class method tries to pass execution to another thread. It depends upon the operating system whether the running thread will switch or not.
Thread priority gives a hint to schedule threads according to their priority. The high priority thread is scheduled first. It also depends upon the operating system. A thread can increase or decrease its own priority as the first action it takes.
Thread Exclusion
Ruby thread exclusion states that, when two threads share the same data and one of the thread modifies that data, then we need to ensure that no thread should see each others data in an inconsistent state. For example, banking server. Where one thread operates money transfer in accounts and other thread is generating monthly report for the customers.
Public Class Methods
Method | Description |
---|---|
abort_on_exception | It returns the status of global “abort on exception” condition. The default is true. When it is set to true, all threads will abort if an exception is raised in any thread. |
abort_on_exception= | When it is set to true, all threads will abort if an exception is raised. It returns the new state. |
current | It returns the currently executing thread. |
exclusive{block} | It wraps the block in a single, returning the value of the block. |
exit | It terminates the currently running thread and schedules another thread tro run. |
kill(thread) | It causes the given thread to exit. |
fork([args]*){|args| block} | It is basically same as ::new method. |
handle_interrupt(hash){…} | Changes asynchronous interrupt timing. |
list | Returns an array of thread objects for all threads that are either runnable or stopped. |
main | Returns the main thread. |
new{…}/ new(*args, &proc)/ new(*args){|args|…} | It creates a new thread executing the given block. |
pass | It gives the thread scheduler a hint to pass execution to another thread. A running thread may or may not switch depending upon the OS. |
pending_interrupt?(error = nil) | It returns whether or not the asynchronous queue is empty. |
start([args]*){|args|block} | It is basically same as ::new method. |
stop | It stops execution of the current thread, putting it into ‘sleep’ state and schedules execution of another thread. |
Public Instance Methods
Method | Description |
---|---|
thr[sym] | It returns the value of a fiber-local variable using either a string or symbol name. |
thr[sym]= | It creates the value of a fiber-local variable using either a string or symbol name. |
abort_on_exception | It returns status of “abort on exception” for thr. |
abort_on_exception= | When set to true, all threads will abort if an exception is raised in this thr. |
add_trace_func(proc) | Adds proc as a handler for tracing. |
alive? | It returns true if thr is running or sleeping. |
backtrace | It returns current backtrace of target ahead. |
backtrace_locations(*args) | It returns the execution stack for the target ahead. |
exit/kill/terminate | It terminates thr and executes another thread to run. |
group | It returns the ThreadGroup which contains the given thread or returns nil. |
inspect | It dumps the name, id and status of thr to a string. |
join | The calling thread will suspend execution and run this thr. |
key?(sym) | It returns true if the given string exists as a fiber-local variable. |
keys | It returns an array of the name of the fiber-local variables. |
pending_interrupt?(error=nil) | Returns whether or not the asynchronous queue is empty for the target thread. |
priority | It returns the priority of thr. |
priority= | It sets the priority of thr to integer. |
kill | It works same as exit. |
raise | It raises an exception from the given thread. |
run | It wakes up thr, making it eligible for scheduling. |
safe_level | It returns the safe level in effect for thr. |
set_trace_func(proc) | It establishes proc on thr as the handler. |
status | It returns the status of thr. |
stop? | It returns true if thr is sleeping or dead. |
terminate | It terminates thr and schedules another thread to run. |
thread_variable?(key) | It returns true if the given string exists as a thread local variable. |
thread_variable_get(key) | It returns the value of a thread local variable that has been set. |
thread_variable_set(key, value) | Set a thread local with key to value. |
thread_variable | It returns an array of the thread-local variables. |
value | It waits for thr to complete, using join and returns its value. |
wakeup | Makes a given thread eligible for scheduling, although it may still remained block on I/O. |
Leave a Reply