Python多线程1:threading

threading模块提供了高级别的线程接口,基于低级别的_thread模块实现。

模块基本方法

该模块定了的方法如下:threading.active_count() 返回当前活跃的Thread对象数量。返回值和通过enumerate()返回的列表长度是相等的。threading.current_thread() 返回当前线程对象,对应调用者的控制线程。如果调用者的控制线程不是通过threading模块创建,一个功能受限的虚拟线程被返回。threading.get_ident() 返回当前线程的“线程标识符”。这是一个非0整数,没有特定含义,通常用于索引线程特定数据的字典。线程标识符可以被循环使用。threading.enumerate() 返回当前活跃的所有线程对象的列表。该列表包括精灵线程、被current_thread()创建的虚拟线程对象、和主线程。它不包括终止的线程和还没有启动的线程。threading.main_thread() 返回主线程对象。在正常情况下,主线程就是Python解释器启动的线程。threading.settrace(func) 为所有从threading模块启动的线程设置一个trace函数。在每个线程的run()方法被调用前,函数将为每个线程被传递到sys.settrace()。threading.setprofile(func) 为所有从threading模块启动的线程设置一个profile函数。在每个线程的run()方法被调用前,函数将为每个线程被传递到sys.setprofile() 。threading.stack_size([size]) 返回当创建一个新线程是使用的线程栈大小,0表示使用平台或配置的默认值。平台顶一个常量如下:threading.TIMEOUT_MAX 阻塞函数(Lock.acquire()、RLock.acquire()、Condition.wait()等)的超时参数允许的最大值。指定的值超过该值将抛出OverflowError。该模块也定义了一些类,在下面会讲到。该模块的设计是仿照Java的线程模型。然而,Java使lock和condition变量成为每个对象的基本行为,在Python中则是分离的对象。Python的Thread类支持Java的线程类的行为的一个子集;当前,,没有优先级,没有线程组,并且线程不能被销毁、停止、暂停、恢复、或者中断。当实现时,Java的线程类的静态方法被对应到模块级函数。形容在下面的所有方法都被原子地执行。

线程本地数据

线程本地数据是那些值和特定线程相关的数据。为了管理线程本地数据,创建一个local类(或者一个子类)的实例,然后存储属性在它里面:

mydata = threading.local()mydata.x = 1为不同线程实例的值将是不同的。class threading.local表示线程本地数据的类。更多的细节参考_threading_local的文档字符串。

线程对象

Thread类表示一个运行在一个独立的控制线程中的行为。有两个方法指定这个行为:通过传递一个callable对象给构造函数,或者通过在子类中重载run()方法,在子类中没有其他方法(除了构造函数)应该被重载,换句话说,仅重载这个类的__init__()和run()方法。一旦一个线程对象被创建,他的行为必须通过线程的start()方法启动,这将在一个独立的控制线程中调用run()方法。一旦线程的行为被启动,这个线程被认为是’活跃的’。正常情况下,当它的run()终止时它推出活跃状态,或者出现为处理的异常。is_alive()方法可用于测试线程是否活跃。其它线程能调用一个线程的join()方法。这将阻塞调用线程直到join()方法被调用的线程终止。一个线程有一个名称,名称能被传递给构造器,并可以通过name属性读取或者改变。一个线程能被标注为“精灵线程”。这个标志的意义是当今有精灵线程遗留时,Python程序将退出。初始值从创建的线程继承,这个标志可以通过daemon属性设置,或者通过构造器的daemon参数传入。注意,精灵线程在关闭时会突然地停止,他们的资源(例如打开的文件、数据库事务等)不能被正确的释放。如果你想你的线程优雅地停止,应该使它们是非精灵线程并且使用一个适当的信号机制,例如Event(后面讲解)。有一个“主线程”对象,这对应到Python程序的初始控制线程,它不是精灵线程。有可能“虚拟线程对象”被创建,则会存在线程对象对应到“外星人线程”,其控制线程在threading模块之外启动,例如直接从C代码启动。虚拟线程对象的功能是受限的,它们总是被认为是活跃的精灵线程,不能被join()。他们不能被删除,由于探测外星人线程的终止是不可能的。下面是Thread类的构造方法:class threading.Thread(group=None, target=None, name=None, args=(), kwargs={}, *, daemon=None)1)group:应该是None,保留为未来的扩展,当一个ThreadGroup类被实现的时候需要;2)target:一个callable对象,被run()方法调用,默认为None,意味着什么都不做;3)name:线程名,默认情况下,一个形式为“Thread-N”的唯一名被构造,N是一个小的十进制数;4)args:调用target的参数元组,默认为();5)kwargs:为target调用的参数字典,默认为{};6)daemon:如果不为None,则设置该线程是否为精灵线程。如果为None,则从当前线程继承;如果子类覆盖了构造器,在做其它任何事情之前,它必须确保先调用基类的构造器(Thread.__init__())。线程的常用方法如下:1)start()启动线程。每个线程最多只能调用一次。它会导致对象的run()方法在独立的控制线程中被调用。如果在同一个线程对象上调用超过一次将抛出RuntimeError。2)run()表示线程行为的方法。你可以在子类中重载该方法。标准的run()方法调用传入到构造器中callable对象(对应target参数),使用对应的args或者kwargs参数。3)join(timeout=None)等待直到线程结束。这将阻塞当前线程直到join()方法被调用的线程终止或者抛出一个未处理的异常,或者设置的溢出时间到达。如果timeout参数指定且为非None,则它应该是一个浮点数,用于指定操作的溢出时间,单位为秒。由于join()总是返回None,因此在join()结束后你必须调用is_alive()来判断线程是否结束,如果线程任然是活跃的,join()调用则是时间溢出。当timeout不被指定,或者指定为None时,操作将阻塞直到线程终止。一个线程能被join()多次。如果一个join当前线程的尝试将导致一个死锁,join()将抛出RuntimeError。在一个线程启动之前对该线程做join()操作也将导致同样的异常。4)name线程名,仅用于标识一个线程,没有语义,多个线程可以被给同样的名字,初始的名称被构造器设置。5)getName() setName()name的旧的getter/setter API,现在直接使用name属性代替。6)ident这个线程的“线程标识符”,如果线程没有启动,则为None。这是一个非0整数。线程标识符可以被循环使用,一个线程退出后它的线程标识符可以被其它线程使用。7)is_alive()返回线程是否活跃。该方法只有在run()启动后并且在终止之前才返回True。模块函数enumerate()返回所有活跃线程的一个列表。8)daemon一个布尔值,用于表示该线程是否精灵线程。该值必须在start()方法调用之前设置,否则RuntimeError被抛出。它的初始值从创建的线程继承。主线程不是一个精灵线程,因此所有在主线程中创建的线程daemon默认为False。当没有活跃的非精灵线程运行时,整个Python程序退出。9)isDaemon() setDaemon()老的getter/setter API,现在直接使用daemon属性代替。

Lock对象真正的爱,应该超越生命的长度心灵的宽度灵魂的深度

Python多线程1:threading

相关文章:

你感兴趣的文章:

标签云: