Understanding python multi threading (python multi threading tutorial)

  • 2020-04-02 13:44:39
  • OfStack

I spent a lot of time trying to understand python's multithreading, and most of the articles I searched for were not easy to understand. So, here's an attempt to give you an idea of multithreading with a simple example.

Single thread

In the days of ms-dos a few years ago, the operating system was single-tasking. I wanted to do two things: listening to music and watching movies, so I had to prioritize.

(okay! We don't wonder if there were apps for listening to music and watching movies in the DOS era. ^_^)


from time import ctime,sleep
def music():
    for i in range(2):
        print "I was listening to music. %s" %ctime()
        sleep(1)
def move():
    for i in range(2):
        print "I was at the movies! %s" %ctime()
        sleep(5)
if __name__ == '__main__':
    music()
    move()
    print "all over %s" %ctime()

We listened to a piece of music first, controlled the music to play twice through the for loop, each music to play took 1 second, sleep() to control the length of the music. Then we saw a movie,

Each movie took five seconds, and I watched it twice through the for loop because it was so good. After the whole recreational activity was over, I passed


print "all over %s" %ctime()

Looking at the current time, it's almost time to go to bed.

Operation results:


>>=========================== RESTART ================================
>>> 
I was listening to music. Thu Apr 17 10:47:08 2014
I was listening to music. Thu Apr 17 10:47:09 2014
I was at the movies! Thu Apr 17 10:47:10 2014
I was at the movies! Thu Apr 17 10:47:15 2014
all over Thu Apr 17 10:47:20 2014

Actually, music() and move() should be thought of more as music and video players, and it's up to us to decide which songs and videos to play. So, we modified the above code:


#coding=utf-8
import threading
from time import ctime,sleep
def music(func):
    for i in range(2):
        print "I was listening to %s. %s" %(func,ctime())
        sleep(1)
def move(func):
    for i in range(2):
        print "I was at the %s! %s" %(func,ctime())
        sleep(5)
if __name__ == '__main__':
    music(u' Love buying and selling ')
    move(u' "Avatar" ')
    print "all over %s" %ctime()

Music () and move() are handled by passing arguments. Experience Chinese classic songs and European and American blockbusters.

Operation results:


>>> ======================== RESTART ================================
>>> 
I was listening to  Love buying and selling . Thu Apr 17 11:48:59 2014
I was listening to  Love buying and selling . Thu Apr 17 11:49:00 2014
I was at the  "Avatar" ! Thu Apr 17 11:49:01 2014
I was at the  "Avatar" ! Thu Apr 17 11:49:06 2014
all over Thu Apr 17 11:49:11 2014

multithreading

In the development of science and technology, the progress of The Times, our CPU is faster and faster, the CPU complained, P big things take up a certain amount of my time, in fact, I do a number of work are no problem; So, operations

This is the age of multitasking. We listened to the music and ate the hot pot is no longer a dream.

Python provides two modules to implement multi-threading thread and threading, thread has some shortcomings in threading got compensated for, in order not to waste you and time, so we straight

Then just learn about threading.

Continue with the above example and introduce threadring to play both music and video:


#coding=utf-8
import threading
from time import ctime,sleep

def music(func):
    for i in range(2):
        print "I was listening to %s. %s" %(func,ctime())
        sleep(1)
def move(func):
    for i in range(2):
        print "I was at the %s! %s" %(func,ctime())
        sleep(5)
threads = []
t1 = threading.Thread(target=music,args=(u' Love buying and selling ',))
threads.append(t1)
t2 = threading.Thread(target=move,args=(u' "Avatar" ',))
threads.append(t2)
if __name__ == '__main__':
    for t in threads:
        t.setDaemon(True)
        t.start()
    print "all over %s" %ctime()

The import threading

First, import the threading module, which is a prerequisite for using multithreading.


threads = []
t1 = threading.Thread(target=music,args=(u' Love buying and selling ',))
threads.append(t1)

Create the threads array, create the Thread t1, use the threading.Thread() method, in this method call the music method target=music, args method to pass to music. The gen

The constructed thread t1 is loaded into the threads array.

Then create the thread t2 in the same way and load the t2 into the threads array as well.



for t in threads:
  t.setDaemon(True)
  t.start()

Finally, the groups are iterated through the for loop. (the array is loaded with t1 and t2 threads)

SetDaemon ()

SetDaemon (True) declares a thread as a daemon thread and must be set before the start() method is called, otherwise the program will be suspended indefinitely. After the child thread starts, the parent line

Program also continues to execute, when the parent thread executed the last statement print "all over %s" %ctime(), did not wait for the child thread, directly exit, at the same time the child thread also ended.

Start ()

Start thread activity.
Operation results:


>>> ========================= RESTART ================================
>>> 
I was listening to  Love buying and selling . Thu Apr 17 12:51:45 2014 I was at the  "Avatar" ! Thu Apr 17 12:51:45 2014  all over Thu Apr 17 12:51:45 2014

From the execution result, the child thread (muisc, move) and the main thread (print "all over %s" %ctime()) are all started at the same time, but because the main thread finishes execution, the child thread also terminates.

Continue to adjust procedures:


...
if __name__ == '__main__':
    for t in threads:
        t.setDaemon(True)
        t.start()

    t.join()
    print "all over %s" %ctime()

We just added a join() method to the program above to wait for the thread to terminate. The join () effect is that the parent of the child thread will remain blocked until the child thread completes its run.

Note:   The join() method is outside the for loop, which means that you must wait for both processes in the for loop to finish before executing the main process.

Operation results:


>>> ========================= RESTART ================================
>>> 
I was listening to  Love buying and selling . Thu Apr 17 13:04:11 2014  I was at the  "Avatar" ! Thu Apr 17 13:04:11 2014
I was listening to  Love buying and selling . Thu Apr 17 13:04:12 2014
I was at the  "Avatar" ! Thu Apr 17 13:04:16 2014
all over Thu Apr 17 13:04:21 2014

As you can see from the execution results, music and move are started at the same time.

The start time is 4 minutes and 11 seconds, and the total time is 10 seconds until the main process is called for 4 minutes and 22 seconds. By taking 2 seconds off of a single thread, we can change music's sleep() time to 4 seconds.


...
def music(func):
    for i in range(2):
        print "I was listening to %s. %s" %(func,ctime())
        sleep(4)
...

Execution results:


>>> ====================== RESTART ================================
>>> 
I was listening to  Love buying and selling . Thu Apr 17 13:11:27 2014I was at the  "Avatar" ! Thu Apr 17 13:11:27 2014
I was listening to  Love buying and selling . Thu Apr 17 13:11:31 2014
I was at the  "Avatar" ! Thu Apr 17 13:11:32 2014
all over Thu Apr 17 13:11:37 2014

The child thread starts in 11 minutes and 27 seconds, and the main thread runs in 11 minutes and 37 seconds.

Although music has been extended from 1 second to 4 seconds per song, the total time has not changed since the script was run in the way of multi-path lines.

This article gives you a quick and sensible understanding of the use of python multithreading. Please refer to other documents or materials for more details.

  = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =

Class threading.Thread() description:



class threading.Thread(group=None, target=None, name=None, args=(), kwargs={})
This constructor should always be called with keyword arguments. Arguments are:
  group should be None; reserved for future extension when a ThreadGroup class is implemented.
  target is the callable object to be invoked by the run() method. Defaults to None, meaning nothing is called.
  name is the thread name. By default, a unique name is constructed of the form  " Thread-N "  where N is a small decimal number.
  args is the argument tuple for the target invocation. Defaults to ().
  kwargs is a dictionary of keyword arguments for the target invocation. Defaults to {}.
If the subclass overrides the constructor, it must make sure to invoke the base class constructor (Thread.__init__()) before doing 
anything else to the thread.


I wrote a blog post about multithreading before, and I feel like I haven't finished yet. Actually, multithreading is very interesting. Because we use computers all the time in the process of multi-process and multi-threading. And we can pick up where we left off. Please read my last blog first.


From the above example, we can see that thread creation is quite troublesome. Each thread creation needs to create a tx (t1, t2,...). This is extremely inconvenient if multiple threads are created. The following is to continue to improve through examples:

Player. Py


#coding=utf-8
from time import sleep, ctime 
import threading
def muisc(func):
    for i in range(2):
        print 'Start playing :  %s! %s' %(func,ctime())
        sleep(2)

def move(func):
    for i in range(2):
        print 'Start playing :  %s! %s' %(func,ctime())
        sleep(5)
def player(name):
    r = name.split('.')[1]
    if r == 'mp3':
        muisc(name)
    else:
        if r == 'mp4':
            move(name)
        else:
            print 'error: The format is not recognized!'
list = [' Love buying and selling .mp3',' "Avatar" .mp4']
threads = []
files = range(len(list))
# Create a thread 
for i in files:
    t = threading.Thread(target=player,args=(list[i],))
    threads.append(t)
if __name__ == '__main__': 
    # Starting a thread 
    for i in files:
        threads[i].start() 
 for i in files:
   threads[i].join()
    # The main thread 
    print 'end:%s' %ctime()

Interestingly, we also created a player() function that determines the type of file to play. If it's in mp3 format, we'll call the music() function, and if it's in mp4 format we'll call the move() function. Which of the two formats are not so can only tell the user you provide the file I can not play.

Next, we create a list of files for list, noting the suffix. And then we're going to use len of list to figure out how many files are in the list, just to help us figure out the number of loops.

We then add the files from the list to the threads[] array of threads through a for loop. The threads[] thread group is then started and the end time is printed.

        A split() can split a string into two parts and then take a part of it.



>>> x = 'testing.py'
>>> s = x.split('.')[1]
>>> if s=='py':
    print s
    
py

Operation results:


Start playing :   Love buying and selling .mp3! Mon Apr 21 12:48:40 2014
Start playing :   "Avatar" .mp4! Mon Apr 21 12:48:40 2014
Start playing :   Love buying and selling .mp3! Mon Apr 21 12:48:42 2014
Start playing :   "Avatar" .mp4! Mon Apr 21 12:48:45 2014
end:Mon Apr 21 12:48:50 2014

Now add a file to the list array, and the program will automatically create a thread for it when it runs.


Examples of continued improvement:

Through the above program, we found that the player() is used to determine the file extension, and then call music() and move(), in fact, music() and move() work completely the same, why not make a super player, no matter what file can play. After the transformation, my super player was born.

Super_player. Py


#coding=utf-8
from time import sleep, ctime 
import threading
def super_player(file,time):
    for i in range(2):
        print 'Start playing :  %s! %s' %(file,ctime())
        sleep(time)
# Playback file and duration 
list = {' Love buying and selling .mp3':3,' "Avatar" .mp4':5,' You and me .mp3':4}
threads = []
files = range(len(list))
# Create a thread 
for file,time in list.items():
    t = threading.Thread(target=super_player,args=(file,time))
    threads.append(t)
if __name__ == '__main__': 
    # Starting a thread 
    for i in files:
        threads[i].start() 
  for i in files:
      threads[i].join()
    # The main thread 
    print 'end:%s' %ctime()
 

First, create the dictionary list to define the length (seconds) of the file to be played, and then loop through the dictionary's items() method to fetch the file and time. These two values are used to create the thread.

The super_player() function is then created to receive the file and time to determine the length of the file to be played.

Finally, the thread starts to run. Operation results:


Start playing :   Love buying and selling .mp3! Fri Apr 25 09:45:09 2014
Start playing :   You and me .mp3! Fri Apr 25 09:45:09 2014
Start playing :   "Avatar" .mp4! Fri Apr 25 09:45:09 2014
Start playing :   Love buying and selling .mp3! Fri Apr 25 09:45:12 2014
Start playing :   You and me .mp3! Fri Apr 25 09:45:13 2014
Start playing :   "Avatar" .mp4! Fri Apr 25 09:45:14 2014
end:Fri Apr 25 09:45:19 2014

 

Create your own multithreaded class


#coding=utf-8
import threading 
from time import sleep, ctime 

class MyThread(threading.Thread):
    def __init__(self,func,args,name=''):
        threading.Thread.__init__(self)
        self.name=name
        self.func=func
        self.args=args

    def run(self):
        apply(self.func,self.args)

def super_play(file,time):
    for i in range(2):
        print 'Start playing :  %s! %s' %(file,ctime())
        sleep(time)

list = {' Love buying and selling .mp3':3,' "Avatar" .mp4':5}
# Create a thread 
threads = []
files = range(len(list))
for k,v in list.items():
    t = MyThread(super_play,(k,v),super_play.__name__)
    threads.append(t)        
if __name__ == '__main__': 
    # Starting a thread 
    for i in files:
        threads[i].start() 
  for i in files:
      threads[i].join()
    # The main thread 
    print 'end:%s' %ctime()

MyThread (threading. Thread)

Create the MyThread class to inherit from the threading.thread class.


__init__ ()

Class initialization methods are used to initialize parameters such as func, args, name, etc.  

The apply ()

The apply(func [, args [, kwargs]]) function is used to call a function indirectly when the function argument already exists in a tuple or dictionary. Args is a tuple that contains the arguments passed by position that will be supplied to the function. If args is omitted, no arguments are passed. Kwargs is a dictionary that contains keyword arguments.

Usage: apply ()

 


# Method with no arguments 
>>> def say():
    print 'say in'
>>> apply(say)
say in
# The function takes only tuple arguments 
>>> def say(a,b):
    print a,b
>>> apply(say,('hello',' Insect division '))
hello  Insect division 
# The function takes a keyword argument 
>>> def say(a=1,b=2):
    print a,b
    
>>> def haha(**kw):
    apply(say,(),kw)
    
>>> haha(a='a',b='b')
a b

MyThread (super_play, (k, v), super_play __name__)

Since the MyThread class inherits the threading.thread class, we can use the MyThread class to create threads.

Operation results:


Start playing :   Love buying and selling .mp3! Fri Apr 25 10:36:19 2014
Start playing :   "Avatar" .mp4! Fri Apr 25 10:36:19 2014
Start playing :   Love buying and selling .mp3! Fri Apr 25 10:36:22 2014
Start playing :   "Avatar" .mp4! Fri Apr 25 10:36:24 2014
all end: Fri Apr 25 10:36:29 2014


Related articles: