Python threading(多线程)

2019/01/30 18:44
阅读数 24

   threading模块在较低级别thread模块之上构建更高级别的线程接口。

 

一、threading模块定义了以下函数和对象:

  threading.active_count()
    等同于threading.activeCount(),返回Thread当前活动的对象数。返回的计数等于返回的列表的长度enumerate()。

  threading.Condition()
    返回新条件变量对象的工厂函数。条件变量允许一个或多个线程等待,直到另一个线程通知它们。

  threading.current_thread()
    等同于currentThread(),返回当前Thread对象,对应于调用者的控制线程。如果未通过threading模块创建调用者的控制线程,则返回具有有限功能的虚拟线程对象。

  threading.enumerate()
    返回Thread当前活动的所有对象的列表。该列表包括守护线程,由其创建的虚拟线程对象 current_thread()和主线程。它排除了尚未启动的已终止线程和线程。

  threading.Event()
    返回新事件对象的工厂函数。事件管理一个标志,该标志可以使用该set()方法设置为true,并使用该方法重置为false clear()。该wait()方法将阻塞,直到该标志为真。

  class threading.local
    表示线程本地数据的类。线程局部数据是其值是线程特定的数据。要管理线程本地数据,只需创建一个local(或子类)实例并在其上存储属性。

  threading.Lock()
    返回新原始锁定对象的工厂函数。一旦线程获得它,后续尝试获取它就会阻塞,直到它被释放; 任何线程都可以释放它。

  threading.RLock()
    返回新的可重入锁定对象的工厂函数。必须由获取它的线程释放可重入锁。一旦线程获得了可重入锁,同一个线程可以再次获取它而不会阻塞; 线程必须在每次获取它时释放一次。

  threading.Semaphore([ value] )
    返回新信号量对象的工厂函数。信号量管理一个计数器,表示release()呼叫数减去acquire()呼叫数 加上初始值。该acquire()方法在必要时阻止,直到它可以返回而不使计数器为负。如果没有给出,则值默认为1。

  threading.BoundedSemaphore([ value] )
    返回新的有界信号量对象的工厂函数。有界信号量检查以确保其当前值不超过其初始值。如果确实如此,ValueError则提出。在大多数情况下,信号量用于保护容量有限的资源。如果信号量被释放太多次,则表明存在错误。如果没有给出,则值默认为1。

  class threading.Thread
    表示控制线程的类。该类可以以有限的方式安全地进行子类化。

  class threading.Timer
    在指定的时间间隔过后执行函数的线程。

  threading.settrace(func
    为从threading模块启动的所有线程设置跟踪功能。在调用sys.settrace()其run()方法之前,将为每个线程 传递 func。

  threading.setprofile(func
    为从threading模块启动的所有线程设置配置文件功能。在调用sys.setprofile()其run()方法之前,将为每个线程 传递 func。

  threading.stack_size([ size] )
    返回创建新线程时使用的线程堆栈大小。可选的 size参数指定用于后续创建的线程的堆栈大小,并且必须为0(使用平台或配置的默认值)或至少为32,768(32 KiB)的正整数值。

    如果未指定大小,则使用0。如果不支持更改线程堆栈大小,则引发ThreadError。如果指定的堆栈大小无效,则引发ValueError 且堆栈大小不被修改。32kB是目前支持的最小堆栈大小值,以保证解释器本身有足够的堆栈空间。

    请注意,某些平台可能对堆栈大小的值有特定限制,例如要求最小堆栈大小> 32kB或需要以系统内存页面大小的倍数进行分配 - 应参考平台文档以获取更多信息(4kB页面是常见的 ;在没有更具体的信息的情况下,建议的方法是使用4096的倍数作为堆栈大小。

  exception threading.ThreadError
    针对各种与线程相关的错误引发。请注意,许多接口使用RuntimeError而不是ThreadError。

 

二、Thread Objects

  此类表示在单独的控制线程中运行的活动,有两种方法可以指定活动:

  一是将可调用对象传递给构造函数,二是通过覆盖子类中的run()方法,但不要在子类中重写其他方法,换句话说,只覆盖此类的__init __()和run()方法。

  classthreading.Threadgroup = None,target = None,name = None,args =(),kwargs = {}

    应始终使用关键字参数调用此构造函数。参数是:

      group 应该None,在实现ThreadGroup类时保留用于将来的扩展。

      target 是run()方法调用的可调用对象。默认为None,意味着什么都没有被调用。

      name 是线程名称。默认情况下,唯一名称由“Thread- N ” 形式构成,其中N是小十进制数。

      args 是目标调用的参数元组。默认为()。

      kwargs 是目标调用的关键字参数字典。默认为{}。

    如果子类重写构造函数,则必须确保在对线程执行任何其他操作之前调用基类构造函数(Thread .__ init __())。

  start()
    启动线程的活动。

    每个线程对象最多只能调用一次,它安排在一个单独的控制线程中调用对象的 run()方法。

    如果在同一个线程对象上多次调用此方法,则会引发RuntimeError。

  run()
    表示线程活动的方法。

    你可以在子类中覆盖此方法。 标准的 run()方法调用传递给对象构造函数的可调用对象作为目标参数,分别使用args和kwargs参数中的顺序和关键字参数。

  join([ timeout] )
    等待线程终止,这将阻塞调用线程,直到调用其join()方法的线程终止,或者直到发生异常、超时。

    当timeout参数存在且非None时,它应该是一个浮点数,用于指定操作的超时(以秒为单位);反之当timeout参数不存在或为None时,操作将阻塞直到线程终止。

    由于join()总是返回None,你必须在join()之后调用isAlive()来判断是否发生了超时,如果线程仍处于活动状态,则join()调用超时。

    如果在线程启动之前调用join(),则会引发RuntimeError。

  name()
    一个仅用于识别目的字符串,它没有语义。 多个线程可以赋予相同的名称,初始名称由构造函数设置。

    getName()
    setName()

  ident

    该线程的标识符,如果线程尚未启动,则为None,这是一个非零整数。当线程退出并创建另一个线程时,线程标识符可以被回收。 即使在线程退出后,该标识符也可用。

  is_alive()
    等同于isAlive(),返回线程是否存活。

    此方法在run()方法启动之前返回True,直到run()方法终止之后。 模块函数enumerate()返回所有活动线程的列表。

  daemon()
    一个布尔值,指示此线程是否为守护程序线程True 或False。 必须在调用start()之前设置它,否则引发RuntimeError。 它的初始值继承自创建线程,主线程不是守护程序线程,因此在主线程中创建的所有线程都默认为daemon = False。

    isDaemon()
    setDaemon()

 

三、Lock Objects

  原始锁是一种同步原语,在锁定时不属于特定线程。 在Python中,它是当前可用的最低级别同步原语,由线程扩展模块直接实现。

  Lock.acquire([ blocking] )
    获取锁定,blocking或non-blocking。

    当blocking参数设置为True 时调用(默认值),阻塞直到解锁,然后将其设置为锁定并返回True。

    在将blocking参数设置为False的情况下调用时,请勿阻止。如果blocking设置为True的调用将阻塞,则立即返回False;否则,将Lock设置为锁定并返回True。

  Lock.release()
    释放锁定。

    当Lock是锁定时,将其重置为解锁状态,然后返回。如果阻止任何其他线程等待Lock解锁,则只允许其中一个继续执行。

    在未锁定的Lock上调用时,会引发ThreadError。

    

四、RLock Objects

  线程会调用其acquire()方法来锁定Lock,调用其release()方法来解锁Lock,一旦线程拥有Lock它就会返回。

  acquire()/release()可以嵌套调用,只有最终的release()将Lock重置为unlocked并允许在acquire()中阻塞的另一个线程继续进行。

  RLock.acquire([ blocking = 1 ] )
    获取锁定,blocking或non-blocking。

    在不带参数的情况下调用:如果此线程已拥有锁,则将递归级别递增1,并立即返回。否则,如果另一个线程拥有该锁,则阻塞直到锁被解锁。

    Lock解锁后(不属于任何线程),然后获取所有权,将递归级别设置为1,然后返回。如果多个线程被阻塞等待Lock解锁,则一次只能有一个线程获取Lock的所有权。在这种情况下没有返回值。

    在将blocking参数设置为true的情况下调用时,执行与不带参数调用时相同的操作,并返回true。

    在将blocking参数设置为false的情况下调用时,请勿阻止。如果没有参数的调用会阻塞,则立即返回false;否则,执行与不带参数调用时相同的操作,并返回true。

  RLock.release()
    释放锁定,递减递归级别。如果在递减之后它为零,则将Lock重置为未锁定,并且如果阻止任何其他线程等待Lock解锁,则允许其中一个继续进行。如果在递减之后递归级别仍然非零,则Lock保持锁定并由调用线程拥有。

    仅在调用线程拥有Lock时调用此方法。如果在未锁定时调用此方法,则引发RuntimeError。

 

五、Condition Objects

  该类总是与某种锁相关联,默认情况下会创建一个,也可以传入。

  该类具有acquire()和release()方法,这些方法调用相关锁的相应方法。它还有一个wait()方法,以及notify()和notifyAll()方法,只有在调用线程获得锁定时才能调用这三个,否则会引发RuntimeError。

  class threading.Condition([ lock ] )
    如果给出lock参数且非None,则它必须是一个Lock 或RLock对象,并且它被用作底层锁。否则,将创建一个RLock新对象并将其用作基础锁。

  acquire(* args )
    获取底层锁。此方法在底层锁上调用相应的方法; 返回该方法所有值。

  release()
    释放底层锁。此方法在底层锁上调用相应的方法; 没有返回值。

  wait([timeout] )
    等到通知或直到发生超时。如果在调用此方法时调用线程尚未获取锁定,则引发RuntimeError。

    此方法释放底层锁,然后阻塞直到它被另一个线程中的相同条件变量的notify()或notifyAll()调用唤醒,或者直到发生超时。一旦被唤醒或超时,它就会重新获得锁定并返回。

    当timeout参数存在且非None时,它应该是一个浮点数,指定操作的超时(以秒为单位)。

    当底层锁是一个RLock时,它不会使用其release()方法释放,因为当递归多次获取时,这实际上可能无法解锁。相反,使用了RLock类的内部接口,即使多次递归获取也能解锁它。然后,在重新获取锁时,使用另一个内部接口来恢复递归级别。

  notify(n = 1 )
    默认情况下,唤醒一个等待此条件的线程。如果在调用此方法时调用线程尚未获取锁定, 则引发RuntimeError。

    此方法最多唤醒等待条件变量的n个线程,如果没有线程在等待,那么这是一个无用操作。

  notify_all()
    等同于notifyAll(),唤醒符合条件的所有等待线程。此方法就像 notify(),但唤醒所有等待的线程而不是一个。如果在调用此方法时调用线程尚未获取锁定, 则引发RuntimeError。

# Consume one item
cv.acquire()
while not an_item_is_available():
    cv.wait()
get_an_available_item()
cv.release()

# Produce one item
cv.acquire()
make_an_item_available()
cv.notify()
cv.release()

 

六、Semaphore Objects

  Semaphore管理一个内部计数器,该计数器由每个acquire()调用递减,并由每个release()调用递增。 计数器永远不会低于零,当acquire()发现它为零时,它会阻塞,等待其他线程调用release()。

  class threading.Semaphore([ value ] )
    可选参数给出内部计数器一个初始value; 它默认为1。如果给定的值小于0,则引发ValueError。

  acquire([ block] )
    获取信号量。

    在不带参数的情况下调用:如果内部计数器在输入时大于零,则将其减1并立即返回。如果在进入时为零,则阻塞,等待其他线程调用 release()以使其大于零。

    这是通过适当的互锁来完成的,这样如果多个acquire()呼叫被阻止,它们 release()将完全唤醒其中一个。实现可以随机选择一个,因此不应该依赖被阻塞的线程被唤醒的顺序。在这种情况下没有返回值。

    当使用blocking设置为true 调用时,执行与不带参数调用时相同的操作,并返回true。

    当阻塞设置为false 时调用,请勿阻止。如果没有参数的调用会阻塞,则立即返回false; 否则,执行与不带参数调用时相同的操作,并返回true。

  release()
    释放信号量,将内部计数器递增1。当它在进入时为零并且另一个线程正在等待它再次大于零时,唤醒该线程。

 

七、Event Objects

  可以使用set()方法将其标志设置为true,并使用clear()方法将其标志重置为false,wait()方法将阻塞,直到该标志为true。

  class threading.Event
    内部标志初始为false。

  is_set()
  isSet()
    当且仅当内部标志为真时返回true。

  set()
    将内部标志设置为true。等待它变为真的所有线程都被唤醒。wait()一旦标志为真,调用的线程将不会阻塞。

  clear()
    将内部标志重置为false。随后,线程调用 wait()将阻塞,直到set()被调用以再次将内部标志设置为true。

  wait([ timeout] )
    阻止,直到内部标志为真。如果输入时内部标志为真,则立即返回。否则,阻塞直到另一个线程调用 set()将标志设置为true,或者直到发生超时。

    当timeout参数存在且非None时,它应该是一个浮点数,指定操作的超时(以秒为单位)。

    此方法在退出时返回内部标志,因此它将始终返回True, 除非给定超时并且操作超时。

     

八、Timer Objects

   通过调用start()方法启动计时器,通过调用cancel()方法可以停止计时器(在其动作开始之前)。

  class threading.Timer(interval,function,args = [],kwargs = {} )
    创建一个定时器,在经过间隔N秒后,将使用参数args和关键字参数kwargs运行函数。

  cancel()
    停止计时器,取消执行计时器的操作。这仅在定时器仍处于等待阶段时才有效。

def hello():
    print "hello, world"

t = Timer(30.0, hello)
t.start()  # 30秒之后print

 

九、使用with语句

  此模块提供的具有acquire()和 release()方法的所有对象都可以用作with 语句的上下文管理器。

  在输入块时将调用acquire()方法,并在退出块时调用release()方法。

  目前Lock,RLock,Condition, Semaphore,和BoundedSemaphore 对象都可以用作 with声明上下文管理。

import threading

some_rlock = threading.RLock()

with some_rlock:
  print "some_rlock is locked while this executes"

 

展开阅读全文
加载中

作者的其它热门文章

打赏
0
0 收藏
分享
打赏
0 评论
0 收藏
0
分享
返回顶部
顶部
返回顶部
顶部