• 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
  • 相关阅读:
    两个链表的第一个公共节点(Python and C++解法)
    第一个只出现一次的字符(Python and C++解法)
    丑数(Python and C++解法)
    最长不含重复字符的子字符串(Python and C++解法)
    礼物的最大值(Python and C++解法)
    把数字翻译成字符串(Python and C++解法)
    连续子数组的最大和(Python and C++解法)
    最小的k个数(Python and C++解法)
    数组中出现次数超过一半的数字(Python and C++解法)
    字符串的排列(Python and C++解法)
  • 原文地址:https://www.cnblogs.com/tester-xt/p/9387956.html
Copyright © 2020-2023  润新知