threading模块—Python多线程编程

Posted tester_小天

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了threading模块—Python多线程编程相关的知识,希望对你有一定的参考价值。

Threading 模块

threading 模块除了提供基本的线程和锁定支持外,还提供了更高级别、功能更全面的线程管理。threading 模块支持守护线程,其工作方式是:守护线程一般是一个等待客户端请求的服务器,如果没有客户端请求,守护线程就是空闲的。如果把一个线程设置为守护线程,就表示这个线程是不重要的,进程退出时不需要等待这个线程完成。(如何设置守护线程?只需执行赋值语句: thread.daemon = True )

threading 模块的对象:

对象描述
Thread 表示一个执行线程的对象
Lock 锁原语对象(和 thread 模块中的锁一样)
RLock 可重入锁对象,使单一线程可以(再次)获得已持有的锁(锁递归)
Condition 条件变量对象,使得一个线程等待另一个线程满足特定的“条件”,比如改变状态或者某个数据
Event 条件变量的通用版本,任意数量的线程等待某个事件的发生,在该事件发生后所有线程将被激活
Semaphore 为线程间共享的有限资源提供了一个“计数器”,如果没有可用资源时会被阻塞
BoundedSemaphore 与 Semaphore 相似,不过它不允许超过初始值
Timer 与 Thread 相似, 不过它要在运行前等待一段时间
Barrier 创建一个“障碍”,必须达到指定数量的线程后才可以继续
[①]  Python 3.2版本中引入

 

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多线程编程的主要内容,如果未能解决你的问题,请参考以下文章

[代码仓库]Python3多线程编程

Python3 多线程编程 threading模块

python多线程编程

python多线程编程

Python3 多线程编程(threadthreading模块)

41 Python - python并行编程 多线程之——thread模块(已经过时,开发不推荐)