Multithreading in Python (2): threading module, pythonthreading
I mentioned the usage of Python multithreading. Today I will introduce the better threading module, which provides Thread classes and some useful synchronization mechanisms.
First introduce Thread class
The Thread class in the threading module has many methods that are not available in the thread module. You can choose one of the following methods for use:
- Create a Thread instance and pass it a function;
- Create a Thread instance and pass it a callable class object;
- A subclass is derived from Thread to create an instance of this subclass.
Let's see how it works.
| Function |
Description |
| Start () |
Start thread execution |
Run () |
A function that defines the functions of a thread (usually overwritten by the quilt class) |
| Join (timeout = None) |
The program hangs and the thread ends. If timeout is given, a maximum of timeout seconds can be blocked. |
GetName () |
The name of the returned thread. |
| SetName (name) |
Set the thread name |
| IsAlive () |
Boolean indicates whether the thread is still running. |
| IsDaemon () |
Daemon flag of the returned thread |
| SetDaemon (daemonic) |
Set the daemon flag of the thread to daemonic. |
Use the threading module to override our previous example:
import threadingfrom time import sleep, ctimeloops = [4, 2]def loop(nloop, nsec): print 'start loop%s at: %s\n' % (nloop, ctime()), sleep(nsec) print 'loop%s done at: %s\n' % (nloop, ctime()),def main(): print 'starting at: %s\n' % ctime(), threads = [] nloops = range(len(loops)) for i in nloops: t = threading.Thread(target = loop, args=(i,loops[i])) threads.append(t) for i in nloops: threads[i].start() for i in nloops: threads[i].join() print 'all DONE at: %s\n' %ctime(),if __name__ == '__main__': main()
The result is as follows:
>>> starting at: Sun Jan 03 11:37:43 2016start loop0 at: Sun Jan 03 11:37:43 2016start loop1 at: Sun Jan 03 11:37:43 2016loop1 done at: Sun Jan 03 11:37:45 2016loop0 done at: Sun Jan 03 11:37:47 2016all DONE at: Sun Jan 03 11:37:47 2016
Compared with yesterday's lock, we only need to simply use the join () function for each thread.
Join () seems clearer than an infinite loop waiting for lock release. Another important aspect of this function is that it does not need to be called at all. Once the thread starts, it will always execute and know the exit position of the function of the thread.
The above uses a function to be passed to the Thread module. You can also pass an instance of the callable class when creating a Thread for execution when the Thread starts, this is a method that focuses more on objects.
The Code is as follows:
import threadingfrom time import sleep, ctimeloops = [4, 2]class ThreadFunc(object): def __init__(self, func, args, name=''): self.name = name self.func = func self.args = args def __call__(self): self.res = self.func(*self.args)def loop(nloop, nsec): print 'start loop %s at: %s\n' %(nloop, ctime()), sleep(nsec) print 'loop %s done at: %s\n' %(nloop, ctime()),def main(): print 'starting at:', ctime() threads = [] nloops = range(len(loops)) for i in nloops: t = threading.Thread( target = ThreadFunc(loop, (i,loops[i]), loop.__name__)) threads.append(t) for i in nloops: threads[i].start() for i in nloops: threads[i].join() print 'all DONE at:', ctime()if __name__ == '__main__': main()
The result is the same as above, so I will not post it here.
We can see how we got a ThreadFunc class and instantiate a class object that can call ThreadFunc when creating a Thread object.
When a Thread is created, the Thread object calls our ThreadFunc object and uses a special function _ call _ (). Because we already have parameters to use, so it will not be passed to the Thread () constructor.
The last method is to derive a subclass from the Thread class and create an instance of this subclass.
import threadingfrom time import sleep, ctimeloops = [2, 4]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 loop(nloop, nsec): print 'start loop%s at: %s' %(nloop, ctime()) sleep(nsec) print 'loop%s done at:%s' %(nloop, ctime())def main(): print 'starting at:%s' % ctime() threads = [] nloops = range(len(loops)) for i in nloops: t = MyThread(loop, (i, loops[i]), loop.__name__) threads.append(t) for i in nloops: threads[i].start() for i in nloops: threads[i].join() print 'all DONE at: %s' % ctime()if __name__ == '__main__': main()