classmates! It’s class~
Table of Contents
-
Preface
-
The concept of concurrency and parallelism
-
Multithreading
-
Main thread and sub-thread
-
setDaemon() method
-
join() method
-
setName() and getName() methods
-
Multi-threaded disorder and encapsulation
-
disorder
-
encapsulation
Foreword
In today’s era of information explosion, efficient concurrent processing has become a challenge faced by many applications. Multi-threaded programming is a powerful solution in Maxthon Programming World. Through multi-threading, we can execute tasks concurrently and greatly improve program performance.
However, the disorder and encapsulation of multithreading bring a fascinating mystery to the program. The unpredictability of the execution order of threads seems to be weaving an intricate web of threads; and the independent execution of threads shows us a magnificent picture of multiple worlds operating independently at the same time.
The concept of concurrency and parallelism
In Python, concurrency and parallelism are two important concepts used to describe the way a program performs tasks.
Concurrency: The ability to execute multiple tasks at the same time. It can rotate through time slices on a single processor or switch between multiple processors to allow multiple tasks to execute alternately. Concurrency is a logical concept. Multiple tasks can be executed alternately, but not necessarily at the same time.
Parallel: The ability to execute multiple tasks at the same time. It uses the resources of multi-core processors or multiple machines to allocate multiple tasks to different processing units for execution at the same time. Parallelism is a physical concept where multiple tasks are truly executed simultaneously.
In Python, due to the existence of the Global Interpretation Lock (GIL), multi-threading cannot take full advantage of multi-core processors. Therefore, Python’s multi-threading is usually used to handle I/O-intensive tasks (such as network requests, file reading and writing, etc.). It can switch to other threads for execution while waiting for I/O operations to improve the response performance of the program.
If your task is computationally intensive, i.e. requires a lot of CPU calculations, then parallel programming may be more suitable. In Python, you can use the
multiprocessing
module to implement multi-process parallel programming. Each process has an independent GIL and can take advantage of multi-core processors.
It should be noted that concurrency and parallelism are not mutually exclusive and they can exist at the same time. In some cases, we can achieve more efficient programs and make full use of system resources by using multi-threads and multi-processes at the same time.
Multi-threading
Main thread and sub-thread
The main thread is the default thread of the program. It is responsible for executing the main tasks of the program. The ones created through the
start()
method are called child threads.
Here is a simple example code using the main thread and child threads:
import threading import time # Execution function of sub-thread def thread_func(): print("The child thread starts executing") time.sleep(2) # Simulate time-consuming operations print("Sub-thread execution ends") # Main thread print("The main thread starts executing") #Create child thread object t = threading.Thread(target=thread_func) # Start child thread t.start() # The main thread continues to perform other tasks time.sleep(1) print("The main thread performs other tasks") # Wait for the child thread to complete execution t.join() print("Main thread execution ends")
operation result:
The main thread starts execution The child thread starts execution The main thread performs other tasks The execution of the child thread ends Main thread execution ends
In the above example, the main thread first prints a message, then creates the sub-thread object
t
, and callst.start()
to start the sub-thread. After the child thread starts executing, it prints a message, then sleeps for 2 seconds to simulate the time-consuming operation, and finally prints another message. At the same time, the main thread continues to perform other tasks and waits for 1 second before printing a message. The main thread usest.join()
to wait for the child thread to complete execution, and then prints a message to indicate the end of the main thread’s execution.Run the above code, and you will see that the main thread and sub-threads execute alternately, and each thread has an independent execution process. The main thread and sub-threads can perform different tasks concurrently, realizing multi-threaded programming.
setDaemon() method
setDaemon()
is a method provided by theThread
class, which is used to set the daemon attribute of the thread. After setting a thread as a daemon thread, the thread will automatically exit when the main thread exits, regardless of whether the daemon thread has completed execution.The
setDaemon()
method accepts a Boolean parameterdaemon
, and the default value isFalse
. If thedaemon
parameter is set toTrue
, it means that the thread is set as a daemon thread; if it is set toFalse
, it means that the thread is set as a non-daemon thread. daemon thread.
The following is an example of using the
setDaemon()
method, demonstrating the use of daemon threads:
import threading import time # Execution function of sub-thread def thread_func(): print("The child thread starts executing") time.sleep(5) print("Sub-thread execution ends") # Main thread print("The main thread starts executing") #Create child thread object t = threading.Thread(target=thread_func) #Set the child thread as a daemon thread t.setDaemon(True) # Start child thread t.start() # The main thread continues to perform other tasks time.sleep(1) print("The main thread performs other tasks") print("Main thread execution ends")
operation result:
The main thread starts execution The child thread starts execution The main thread performs other tasks Main thread execution ends
In the above example, the main thread creates a child thread object
t
, and then sets the child thread as a daemon thread throught.setDaemon(True)
. The daemon thread will not prevent the main thread from exiting. Even if the daemon thread has not completed execution, the main thread can still exit normally. In this example, the sub-thread performed an operation that took 5 seconds, but because it was set as a daemon thread, the main thread exited immediately after completing other tasks without waiting for the daemon thread to complete execution.It should be noted that the
setDaemon()
method must be called before thestart()
method, otherwise aRuntimeError
exception will be thrown. In addition, once a thread is set as a daemon thread, its daemon properties cannot be modified. Therefore, it is generally recommended to set the guard attribute when creating a thread.
Daemon threads are very useful in certain situations, such as periodically executing some background tasks, monitoring the running status of the program, etc. When using daemon threads, you need to pay attention to the execution status of the daemon threads to ensure that they do not affect the normal operation of the program.
join() method
join()
is a method provided by theThread
class, which is used to wait for the thread to complete execution.The
join()
method can be called in the main thread to block the main thread until the specified thread completes execution. It pauses the execution of the main thread until the called thread completes execution or the specified timeout is exceeded.The
join()
method can take an optional parametertimeout
, which is used to set the maximum waiting time in seconds. If thetimeout
parameter is specified, thejoin()
method will wait for the specified time. If the time exceeds and the thread has not completed execution, the main thread will continue to execute subsequent code. If thetimeout
parameter is not specified, thejoin()
method will block the main thread until the called thread completes execution.
The following is an example using the
join()
method, demonstrating how to wait for the thread to complete execution:
import threading import time # Execution function of sub-thread def thread_func(): print("The child thread starts executing") time.sleep(5) print("Sub-thread execution ends") # Main thread print("The main thread starts executing") #Create child thread object t = threading.Thread(target=thread_func) # Start child thread t.start() # Wait for the child thread to complete execution t.join() print("Main thread execution ends")
operation result:
The main thread starts execution The child thread starts execution The execution of the child thread ends Main thread execution ends
In the above example, the main thread creates a sub-thread object
t
and then starts the sub-thread throught.start()
. Next, the main thread calls thet.join()
method and waits for the child thread to complete execution. During the execution of the sub-thread, the main thread will be blocked and will not continue to execute subsequent code until the sub-thread completes execution.It should be noted that the
join()
method can be called immediately after starting the thread or at any time. If the called thread has completed execution, thejoin()
method will return immediately. In addition, you can check whether the thread is still executing through theis_alive()
method to avoid the main thread being blocked all the time.
The
join()
method is very useful when processing multi-threaded tasks. It can ensure that all thread tasks are completed before subsequent processing, ensuring synchronization and sequence between threads.
setName() and getName() methods
setName()
andgetName()
are two methods provided by theThread
class for setting and getting the name of the thread.The
setName()
method is used to set the name of the thread. It accepts a string parametername
, which represents the thread name to be set.The
getName()
method is used to get the name of the thread. It returns a string representing the name of the thread.
The following is an example using the
setName()
andgetName()
methods to demonstrate how to set and get the name of a thread:
import threading # Execution function of sub-thread def thread_func(): print("The name of the child thread is:", threading.currentThread().getName()) # Main thread print("The name of the main thread is:", threading.currentThread().getName()) #Create child thread object t = threading.Thread(target=thread_func) #Set the name of the child thread t.setName("MyThread") # Get the name of the child thread print("The name of the child thread is:", t.getName()) # Start child thread t.start()
operation result:
The name of the main thread is: MainThread The name of the child thread is: MyThread The name of the child thread is: MyThread
In the above example, the main thread gets its own name through
threading.currentThread().getName()
and prints it out. Then, a sub-thread objectt
is created, and the name of the sub-thread is set to “MyThread” throught.setName("MyThread")
. Next, get the name of the child thread throught.getName()
and print it out. Finally, start the child thread throught.start()
.It is important to note that thread names are very useful for debugging and logging, and can help distinguish different threads. If the thread’s name is not explicitly set, the thread will automatically be assigned a default name.
In addition, the name of the thread can be set by directly modifying the
name
property of theThread
object. For example,t.name = "MyThread"
can achieve the same effect ast.setName("MyThread")
.In actual multi-thread programming, you can usually set a meaningful name for a thread through the
setName()
method to facilitate thread tracking and debugging. Through thegetName()
method, you can obtain the name of the thread when needed for further processing and recording.
Multi-threading disorder and encapsulation
Unordered
In Python multi-threaded programming, out-of-order (no guaranteed sequential execution) and encapsulation (independent threads) are two important concepts.
Disorder means that in the process of multi-thread execution, the execution order of each thread is uncertain, and no sequential assumptions can be made.
Since the thread scheduling mechanism is determined by the operating system, the execution order of threads may be affected by a variety of factors, such as the operating system’s scheduling policy, thread priority, etc. Therefore, the execution results of multi-threaded programs may be different in different running environments.
Here is an example of using multi-threading to demonstrate disorder, where two threads are created that alternately perform printing operations:
import threading #Execution function of thread def thread_func(name): for i in range(5): print(f"Thread {<!-- -->name} executes, prints {<!-- -->i}") #Create thread object t1 = threading.Thread(target=thread_func, args=("Thread 1",)) t2 = threading.Thread(target=thread_func, args=("Thread 2",)) # Start thread t1.start() t2.start()
Running the above code, the possible output results are as follows:
Thread 1 executes and prints 0 Thread 2 executes and prints 0 Thread 1 executes and prints 1 Thread 2 executes and prints 1 Thread 1 executes and prints 2 Thread 2 executes and prints 2 Thread 2 executes and prints 3 Thread 1 executes and prints 3 Thread 2 executes and prints 4 Thread 1 executes and prints 4
It can be seen that the execution order of the two threads is uncertain, and they will alternately perform different tasks. This is the embodiment of disorder.
Encapsulation
Encapsulation means that each thread is an independent execution unit, and they have independent call stacks and execution contexts. Threads do not interfere with each other or share variables (unless specifically designed). This encapsulation ensures thread safety because each thread can perform its own tasks independently without interfering with each other.
The following is an example of using multi-threading to demonstrate encapsulation, in which two threads operate on shared variables separately without interfering with each other:
import threading # Shared variables counter = 0 # Lock lock = threading.Lock() #Execution function of thread def thread_func(): global counter for _ in range(100000): with lock: counter + = 1 #Create thread object t1 = threading.Thread(target=thread_func) t2 = threading.Thread(target=thread_func) # Start thread t1.start() t2.start() # Wait for the thread to complete execution t1.join() t2.join() print("Final result:", counter)
Running the above code, the output result is that the two threads accumulate the shared variable
counter
, and the final output result will be close to 200000. Due to the use of a lock mechanism, each operation oncounter
is guaranteed to be atomic, avoiding issues of race conditions and data inconsistency. This is the embodiment of encapsulation.
Ding ding bell, get out of class is over~ I wish everyone a happy life
Finally:
Python learning materials
If you want to learn Python to help you automate your office, or are preparing to learn Python or are currently learning it, you should be able to use the following and get it if you need it.
① A roadmap for learning Python in all directions, knowing what to learn in each direction ② More than 100 Python course videos, covering essential basics, crawlers and data analysis ③ More than 100 Python practical cases, learning is no longer just theory ④ Huawei’s exclusive Python comic tutorial, you can also learn it on your mobile phone ⑤Real Python interview questions from Internet companies over the years, very convenient for review
There are ways to get it at the end of the article
1. Learning routes in all directions of Python
The Python all-direction route is to organize the commonly used technical points of Python to form a summary of knowledge points in various fields. Its usefulness is that you can find corresponding learning resources according to the above knowledge points to ensure that you learn more comprehensively.
2. Python course video
When we watch videos and learn, we can’t just move our eyes and brain but not our hands. The more scientific learning method is to use them after understanding. At this time, hands-on projects are very suitable.
3. Python practical cases
Optical theory is useless. You must learn to follow along and practice it in order to apply what you have learned to practice. At this time, you can learn from some practical cases.
Four Python Comics Tutorial
Use easy-to-understand comics to teach you to learn Python, making it easier for you to remember and not boring.
5. Internet company interview questions
We must learn Python to find a high-paying job. The following interview questions are the latest interview materials from first-tier Internet companies such as Alibaba, Tencent, Byte, etc., and Alibaba bosses have given authoritative answers. After finishing this set I believe everyone can find a satisfactory job based on the interview information.
This complete version of the complete set of Python learning materials has been uploaded to CSDN. If friends need it, you can also scan the official QR code of csdn below or click on the WeChat card at the bottom of the homepage and article to get the method. [Guaranteed 100% free] strong>