Every program running on the system is a process. Each process contains one or more threads.
Thread is a single sequence control flow in a program, which runs multiple threads to complete different tasks at the same time in a single program, which is called multi-thread.
In Ruby, we can pass through To start a new thread, simply call the The following example shows how to use multithreading in a Ruby program: The result of the above code execution is: 1.Thread creation can be done using the 2.There is no need to start the thread after it is created, and the thread will execute automatically. 3.The Thread class defines some methods to manipulate threads. Thread execution 4.The last statement in the thread code block is the value of the thread, which can be called through the method of the thread. If the thread is finished, the thread value is returned, otherwise the value is not returned until the thread is finished. 5.The 6.Through Threads have five states: Thread state Return value Executable Run sleep Sleeping Quit Aborting Normal termination False Abnormal termination occurred Nil When an exception occurs in a thread and is not subject to Using the following three methods, you can have the interpreter break when athread terminates due to an exception. Specify when you start the script Use Use When using one of the above three methods, the entire interpreter will be interrupted. In Ruby, there are three ways to achieve synchronization, which are: Thread synchronization through Mutex class The Queue class that supervises data handover implements thread synchronization Use Thread synchronization control is implemented through the Mutex class, and if you need a program variable for multiple thread clocks at the same time, you can use lock to lock part of this variable. The code is as follows: The result of the above code execution is: In addition to locking variables using lock, you can also use the The Queue class represents a queue that supports threads and can access the end of the queue synchronously. Different threads can use a unified pair class, but do not worry about whether the data in this queue can be synchronized, and use the The classic producer-consumer problem: Output of the program: A thread can have its own private variable, and the thread’s private variable is written to the thread when it is created. It can be used within the scope of the thread, but cannot be shared outside the thread. But sometimes, what if a thread’s local variables need to be accessed by another thread or the main thread? Ruby provides the ability to create thread variables by name, similar to treating threads as hash-style hash tables. Pass through The output of the above code is as follows: The main thread waits for the child thread to finish execution, and then outputs each value separately. . The priority of the thread is the main factor affecting the scheduling of the thread. Other factors include the amount of execution time consumed by CPU, thread grouping scheduling, and so on. Can be used The priority of the thread defaults to 0. Those with higher priority executefaster. An Thread can access all the data in its scope, but what if you need to access the data of other threads within one thread? The Thread class provides a way for threads to access each other’s data. You can simply use a thread as a Hash table in any thread. As you can see, using the thread as a Hash table, use the Mutex (Mutal Exclusion = mutex) is a mechanism used in multithreaded programming to prevent two threads from reading and writing to the same common resource, such as global variables. The output of the above instance is as follows: The output of the above instance is as follows: When there are more than two computing units, both sides are waiting for theother to stop running in order to obtain system resources, but when no one exits ahead of time, this situation is called deadlock. For example, a process p1 takes up the monitor and must use the printer at the same time, while the printer is occupied by process p2, and p2 must use the monitor, thus forming a deadlock. When we are using The output result of the above example is: The complete Thread class method is as follows: Serial number Method description 1 If the value of Thread.abort_on_exception is true, once a thread terminates due to an exception, the entire interpreter will be interrupted. Its defaultvalue is false, that is, under normal circumstances, if an exception occursto a thread and the exception is not detected by Thread#join, etc., the thread will be terminated without warning. 2 If Thread.abort_on_exception= is set to true, once a thread terminates due to an exception, the entire interpreter will be interrupted. Return to the new status 3 Thread.critical returns a Boolean value. 4 Thread.critical= will not switch threads when its value is true. If the current thread is suspended (stop) or interfered with a signal, itsvalue automatically changes to false. 5 Thread.current returns the currently running thread. 6 Thread.exit terminates the running of the current thread. Returns the current thread. If the current thread is the only thread, exit (0) will be used to terminate its run. 7 Thread.fork {block} generates threads like Thread.new. 8 Thread.kill (aThread) terminates the running of the thread. 9 Thread.list returns an array of live threads in the running or suspended state. 10 Thread.main returns the main thread. 11 Thread.new( [ arg ]* ) {| args | block }Generate a thread and begin execution. The number will be passed to the block intact This allows the value to be passed to the local variables inherent in the thread while starting it. 12 Thread.pass gives the right to run to other threads. It does not change the state of the running thread, but gives control to other runnable threads (explicit thread scheduling). 13 Thread.start( [ args ]* ) {| args | block }Generate a thread and begin execution. The number will be passed to the block intact This allows the value to be passed to the local variables inherent in the thread while starting it. 14 Thread.stop suspends the current thread until another thread wakes it up again using the run method. The following example calls the thread instantiation method The following is a complete list of instantiation methods: Serial number Method description 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
Thread
class to create multithreading, Ruby threads are lightweight and can implement parallel code in an efficientway. 6.44.1. Create a Ruby thread #
Thread.new
:#Thread # 1 Code Section Thread. new
{# Thread # 2 Executing Code} # Thread # 1 Executing Code
6.44.2. Example #
Example #
#!/usr/bin/rubydeffunc1i=0whilei<=2puts"func1 at:
#{Time.now}"sleep(2)i=i+1endenddeffunc2j=0whilej<=2puts"func2 at:
#{Time.now}"sleep(1)j=j+1endendputs"Started At
#{Time.now}"t1=Thread.new{func1()}t2=Thread.new{func2()}t1.joint2.joinputs"End
at #{Time.now}"
Started At Wed May 14 08:21:54 -0700 2014
func1 at: Wed May 14 08:21:54 -0700 2014
func2 at: Wed May 14 08:21:54 -0700 2014
func2 at: Wed May 14 08:21:55 -0700 2014
func1 at: Wed May 14 08:21:56 -0700 2014
func2 at: Wed May 14 08:21:56 -0700 2014
func1 at: Wed May 14 08:21:58 -0700 2014
End at Wed May 14 08:22:00 -0700 2014
6.44.3. Thread life cycle #
Thread.new
can also be used inthe same syntax
Thread.start
or
Thread.fork
, these three methods create threads.
Thread.new
code block .
Thread.current
method returns the object that represents the current thread.
Thread.main
method returns the main thread.
Thread.Join
method to execute the thread, which suspends themain thread until the current thread finishes execution. 6.44.4. Thread state #
6.44.5. Threads and exceptions #
rescue
when captured, the thread is usually terminated without warning. However, if there are other threads because
Thread#join
if the relationship has been waiting for the thread, the waiting thread will be thrown the same exception.begint=Thread.newdoThread.pass#The main thread is indeed waitingjoinraise"unhandled
exception"endt.joinrescuep$!#=> "unhandled exception"end
-d
option and run when debugging the mode.
Thread.abort_on_exception
Set the flag.
Thread#abort_on_exception
Sets the flag for the specified thread.t=Thread.new{ ... }t.abort_on_exception=true
6.44.6. Thread synchronization control #
ConditionVariable
to realize synchronous control 6.44.7. Thread synchronization through Mutex class #
Example #
#!/usr/bin/rubyrequire"thread"puts"Synchronize
Thread"@num=200@mutex=Mutex.newdefbuyTicket(num)@mutex.lockif@num>=num@num=@num-numputs"you
have successfully bought #{num} tickets"elseputs"sorry,no enough
tickets"end@mutex.unlockendticket1=Thread.new10do10.timesdo\|value\|ticketNum
=15buyTicket(ticketNum)sleep0.01endendticket2=Thread.
new10do10.timesdo\|value\|ticketNum=20buyTicket(ticketNum)sleep0.01endendsleep1ticket1.jointicket2.join
Synchronize Thread
you have successfully bought 15 tickets
you have successfully bought 20 tickets
you have successfully bought 15 tickets
you have successfully bought 20 tickets
you have successfully bought 15 tickets
you have successfully bought 20 tickets
you have successfully bought 15 tickets
you have successfully bought 20 tickets
you have successfully bought 15 tickets
you have successfully bought 20 tickets
you have successfully bought 15 tickets
sorry,no enough tickets
sorry,no enough tickets
sorry,no enough tickets
sorry,no enough tickets
sorry,no enough tickets
sorry,no enough tickets
sorry,no enough tickets
sorry,no enough tickets
sorry,no enough tickets
try_lock
lock variables, and you can also use the
Mutex.synchronize
synchronize access to a variable. 6.44.8. The Queue class that supervises data handover implements thread synchronization #
SizedQueue
class can limit the length of the queue
SizedQueue
class can easily help us develop thread synchronization applications, so as long as you join this queue, you don’t have to worry about thread synchronization.Example #
#!/usr/bin/rubyrequire"thread"puts"SizedQuee
Test"queue=Queue.newproducer=Thread.newdo10.timesdo\|i\|sleeprand
(i)#Let the thread sleep for a period of timequeue<<iputs"#{i}
produced"endendconsumer=Thread.newdo10.timesdo\|i\|value=queue.popsleeprand(i/2)
puts "consumed #{value}" end end consumer.join
SizedQuee Test
0 produced
1 produced
consumed 0
2 produced
consumed 1
consumed 2
3 produced
consumed 34 produced
consumed 4
5 produced
consumed 5
6 produced
consumed 6
7 produced
consumed 7
8 produced
9 produced
consumed 8
consumed 9
6.44.9. Thread variable #
[]=
write and pass through
[]
read the data. Let’s look at the following code:Example #
#!/usr/bin/rubycount=0arr=[]10.timesdo\|i\|arr[i]=Thread.new{sleep(rand(0)/10.0)
Thread.current["mycount"] = count count += 1 } end arr.each {|t\|
t.join; print t["mycount"], ", " } puts "count = #{count}"
8, 0, 3, 7, 2, 1, 6, 5, 4, 9, count = 10
6.44.10. Thread priority #
Thread.priority
method to get the priority and use of the thread
Thread.priority=
method to adjust the priority of the thread.
[]=
write data, use
[]
to read the data.athr=Thread.new{Thread.current["name"]="Thread
A";Thread.stop}bthr=Thread.new{Thread.current["name"]="Thread
B";Thread.stop}cthr=Thread.new{Thread.current["name"]="Thread
C";Thread.stop}Thread.list.each{\|x\|puts"#{x.inspect}: #{x["name"]}"}
[]
and
[]=
method, we implement data sharing between threads. 6.44.11. Thread mutual exclusion #
6.44.12. Instances that do not use Mutax #
Example #
#!/usr/bin/rubyrequire'thread'count1=count2=0difference=0counter=
Thread.newdoloopdocount1+=1count2+=1endendspy=Thread.newdoloopdodifference+
=(count1-count2).absendendsleep1puts"count1
: #{count1}"puts"count2 : #{count2}"puts"difference : #{difference}"
count1 : 9712487
count2 : 12501239
difference : 0
6.44.13. An instance of using mutex #
Example #
#!/usr/bin/rubyrequire'thread'mutex=Mutex.newcount1=count2=0difference=0counter=Thread.newdoloopdomutex.synchronizedocount1+=1count2+=1endendendspy=Thread.newdoloopdomutex.synchronizedodifference+=(count1-count2).absendendendsleep1mutex.lockputs"count1
: #{count1}"puts"count2 : #{count2}"puts"difference : #{difference}"
count1 : 1336406
count2 : 1336406
difference : 0
6.44.14. Deadlock #
Mutex
object needs to be aware of thread deadlocks.Example #
#!/usr/bin/rubyrequire'thread'mutex=Mutex.newcv=ConditionVariable.newa=Thread.new{mutex.synchronize{puts"A:
I have critical section, but will wait for cv"cv.wait(mutex)puts"A: I
have critical section again! I rule!"} }puts"(Later, back at the
ranch...)"b=Thread.new{mutex.synchronize{puts"B: Now I am critical, but
am done with cv"cv.signalputs"B: I am still critical, finishing up"}
}a.joinb.join
A: I have critical section, but will wait for cv
(Later, back at the ranch...)
B: Now I am critical, but am done with cv
B: I am still critical, finishing up
A: I have critical section again! I rule!
6.44.15. Thread class method #
6.44.16. Thread instantiation method #
join
:Example #
#!/usr/bin/rubythr=Thread.newdo#instantiate puts"In second thread"raise"Raise
exception"endthr.join#Call Instantiation Method join
thr[
name
]
fetch the inherent data corresponding to name in the thread.name can be a string or symbol. If there is no data corresponding to name, return nil.
thr[
name
]
=
sets the value of the inherent data corresponding to the name in the thread, and the name can be a string or symbol. If set to nil, the corresponding data in the thread will be deleted.
thr.abort_on_exception
Returns a Boolean value.
thr.abort_on_exception=
If the value is true, once a thread terminates due to an exception, the entire interpreter will be interrupted.
thr.alive?
If the thread is “alive”, it returns true.
thr.exit
Terminates the running of the thread. Return to self.
thr.join
Suspends the current thread until the self thread terminates. If the self terminates because of an exception, the current thread throws the same exception.
thr.key?
If the inherent data of the thread corresponding to name has been defined, return true
thr.kill
is similar to Thread.exit.
thr.priority
Returns the priority of the thread. The default value for priority is 0. The higher the value, the higher the priority.
thr.priority=
Set the priority of threads. You can also set it to a negative number.
thr.raise(
anException
)
Forcibly throws an exception within the thread.
thr.run
Restart the suspended (stop) thread. Unlike wakeup, it will switch threads immediately. If you use this method on a dead process, a ThreadError exception will be thrown.
thr.safe_level
Returns the security level of self. The safe_level of thecurrent thread is the same as $SAFE.
thr.status
use the string “run”, “sleep”, or “aborting” is used to represent the state of the living thread. If a thread terminates normally, it returns false. If it is terminated due to an exception, nil is returned.
thr.stop?
If the thread is in a dead state or is stop, it returns true.
thr.value
The return value of the thread’s block is returned after the self thread terminates running (equivalent to join). If an exception occurs while the thread is running, the exception is thrown again.
thr.wakeup
Change the state of a suspended (stop) thread to an executable state (run). If this method is executed on a dead thread, a ThreadError exception will be thrown.