threading模块—Python多线程编程
Posted tester_小天
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了threading模块—Python多线程编程相关的知识,希望对你有一定的参考价值。
threading 模块除了提供基本的线程和锁定支持外,还提供了更高级别、功能更全面的线程管理。threading 模块支持守护线程,其工作方式是:守护线程一般是一个等待客户端请求的服务器,如果没有客户端请求,守护线程就是空闲的。如果把一个线程设置为守护线程,就表示这个线程是不重要的,进程退出时不需要等待这个线程完成。(如何设置守护线程?只需执行赋值语句:
thread.daemon = True
)
threading 模块的对象:
对象 | 描述 |
---|---|
Thread | 表示一个执行线程的对象 |
Lock | 锁原语对象(和 thread 模块中的锁一样) |
RLock | 可重入锁对象,使单一线程可以(再次)获得已持有的锁(锁递归) |
Condition | 条件变量对象,使得一个线程等待另一个线程满足特定的“条件”,比如改变状态或者某个数据 |
Event | 条件变量的通用版本,任意数量的线程等待某个事件的发生,在该事件发生后所有线程将被激活 |
Semaphore | 为线程间共享的有限资源提供了一个“计数器”,如果没有可用资源时会被阻塞 |
BoundedSemaphore | 与 Semaphore 相似,不过它不允许超过初始值 |
Timer | 与 Thread 相似, 不过它要在运行前等待一段时间 |
Barrier① | 创建一个“障碍”,必须达到指定数量的线程后才可以继续 |
Thread 类
threading 模块的 Thread 类是主要的执行对象,它有 thread 模块中没有的很多函数。
Thread 对象的属性和方法:
属性/方法 | 描述 |
---|---|
Thread 对象数据属性 | |
name | 线程名 |
ident | 线程的标识符 |
daemon | 布尔标志,表示这个线程是否是守护线程 |
Thread 对象方法 | |
_init_(group=None, tatget=None, name=None, args=(), kwargs={}, verbose=None, daemon=None) | 实例化一个线程对象,需要有一个可调用的 target,以及其参数 args 或 kwargs 。还可以传递 name 或 group 参数,不过后者还未实现。此外, verbose 标志也是可接受的。 而 daemon 的值将会设定 thread.daemon 属性/标志 |
start() | 开始执行线程 |
run() | 定义线程功能的方法(通常在子类中被应用开发者重写) |
join(timeout=None) | 直至启动的线程终止之前一直挂起,除非给出了 timeout (单位为秒),否则会一直阻塞 |
is_alive() | 布尔标志,表示这个线程是否还存活 |
使用 Thread 类可以有很多种方法创建线程,比如:
-
创建 Thread 的实例,传给它一个函数;
-
创建 Thread 的实例,传给它一个可调用的类实例;
-
派生 Thread 的子类,并创建子类的实例。
*注:一般选择第一个和第三个,当需要一个更加符合面向对象的接口时选择第三个
创建 Thread 的实例,传给它一个函数
使用 threading 模块(mtsleepC.py):
*注:threading 模块的 Thread 类中有个 join() 方法,可以让主线程等待所有线程执行完毕。
1 import threading 2 from time import sleep, ctime 3 ? 4 loops = [4,2] 5 ? 6 def loop(nloop, nsec): 7 print(‘start loop %s at:%s‘ % (nloop, ctime())) 8 sleep(nsec) 9 print(‘loop %s done at:%s‘ % (nloop, ctime())) 10 ? 11 def main(): 12 print("starting at:%s" % ctime()) 13 threads = [] 14 nloops = range(len(loops)) 15 ? 16 for i in nloops: 17 t = threading.Thread(target=loop, args=(i, loops[i])) 18 threads.append(t) 19 ? 20 for i in nloops: 21 threads[i].start() 22 ? 23 for i in nloops: 24 threads[i].join() 25 ? 26 print(‘all DONE at:%s‘ % ctime()) 27 ? 28 ? 29 if __name__ == ‘__main__‘: 30 main()
运行后输出结果:
1 $ mtsleepC.py 2 starting at:Mon Jul 23 12:44:48 2018 3 start loop 0 at:Mon Jul 23 12:44:48 2018 4 start loop 1 at:Mon Jul 23 12:44:48 2018 5 loop 1 done at:Mon Jul 23 12:44:50 2018 6 loop 0 done at:Mon Jul 23 12:44:52 2018 7 all DONE at:Mon Jul 23 12:44:52 2018
实例化每个 Thread 对象时,把函数(target)和参数(args)传进去,然后得到返回的 Thread 实例。实例化 Thread 和调用 thread.start_new_thread() 的最大区别就是新线程不会立即执行。当所有线程分配完后,通过调用每个线程的 start() 方法让他们开始执行。join() 方法将等待线程结束,或者超过提供的时间自动结束。对 join() 方法而言,它根本不需要调用,一旦线程启动它就会一直执行,直到给定的函数完成后退出。
创建 Thread 的实例,传给它一个可调用的类实例
使用可调用的类(mtsleepD.py):
*注:本例中将传递进去一个可调用类(实例)而不仅仅是一个函数。提供了更加面向对象的方法
1 import threading 2 from time import sleep, ctime 3 ? 4 loops = [4,2] 5 ? 6 class ThreadFunc(object): 7 ? 8 def __init__(self, func, args, name=‘‘): 9 self.name = name 10 self.func = func 11 self.args = args 12 ? 13 def __call__(self): 14 self.func(*self.args) 15 ? 16 def loop(nloop, nsec): 17 print(‘start loop %s at:%s‘ % (nloop, ctime())) 18 sleep(nsec) 19 print(‘loop %s done at:%s‘ % (nloop, ctime())) 20 ? 21 def main(): 22 print(‘starting at:%s‘ % ctime()) 23 threads = [] 24 nloops = range(len(loops)) 25 ? 26 for i in nloops: # 创建所有线程 27 t = threading.Thread( 28 target=ThreadFunc(loop, (i, loops[i]),loop.__name__) 29 ) 30 threads.append(t) 31 ? 32 for i in nloops: # 启动所有线程 33 threads[i].start() 34 ? 35 for i in nloops: # 等待结束 36 threads[i].join() 37 ? 38 print(‘all DONE at:%s‘ % ctime()) 39 ? 40 ? 41 if __name__ == ‘__main__‘: 42 main()
运行后的输出结果:
1 $ mtsleepD.py 2 starting at:Tue Jul 24 09:02:32 2018 3 start loop 0 at:Tue Jul 24 09:02:32 2018 4 start loop 1 at:Tue Jul 24 09:02:32 2018 5 loop 1 done at:Tue Jul 24 09:02:34 2018 6 loop 0 done at:Tue Jul 24 09:02:36 2018 7 all DONE at:Tue Jul 24 09:02:36 2018
派生 Thread 的子类,并创建子类的实例
子类化的 Thread(mtsleepE.py):
*注:本例中将对 Thread 子类化,而不是直接对其实例化。这将使我们在定制线程对象时拥有更多灵活性,也能够简化线程创建的调用过程。
1 import threading 2 from time import sleep, ctime 3 ? 4 loops = [4,2] 5 ? 6 class MyThread(threading.Thread): 7 ? 8 def __init__(self, func, args, name=‘‘): 9 threading.Thread.__init__(self) 10 self.name = name 11 self.func = func 12 self.args = args 13 ? 14 def run(self): 15 self.func(*self.args) 16 ? 17 def loop(nloop, nsec): 18 print(‘start loop %s at:%s‘ % (nloop, ctime())) 19 sleep(nsec) 20 print(‘loop %s done at:%s‘ % (nloop, ctime())) 21 ? 22 def main(): 23 print(‘starting at:%s‘ % ctime()) 24 threads = [] 25 nloops = range(len(loops)) 26 ? 27 for i in nloops: # 创建所有线程 28 t = MyThread(loop, (i, loops[i]), loop.__name__) 29 threads.append(t) 30 ? 31 for i in nloops: # 启动所有线程 32 threads[i].start() 33 ? 34 for i in nloops: # 等待结束 35 threads[i].join() 36 ? 37 print(‘all DONE at:%s‘ % ctime()) 38 ? 39 ? 40 if __name__ == ‘__main__‘: 41 main()
运行后的输出结果:
1 $ mtsleepE.py 2 starting at:Tue Jul 24 09:13:49 2018 3 start loop 0 at:Tue Jul 24 09:13:49 2018 4 start loop 1 at:Tue Jul 24 09:13:49 2018 5 loop 1 done at:Tue Jul 24 09:13:51 2018 6 loop 0 done at:Tue Jul 24 09:13:53 2018 7 all DONE at:Tue Jul 24 09:13:53 2018
threading 模块的其它函数
函数 | 描述 |
---|---|
active_count() | 当前活动的 Thread 对象个数 |
current_thread | 返回当前活动的 Thread 对象 |
enumerate() | 返回当前活动的 Thread 对象列表 |
settrace(func) | 为所有线程设置一个 trace 函数 |
setprofile(func) | 为所有线程设置一个 profile 函数 |
stack_size(size=0) | 返回新创建线程的栈大小;或为后续创建的线程设定栈的大小为 size |
以上是关于threading模块—Python多线程编程的主要内容,如果未能解决你的问题,请参考以下文章