PythonTip >> 博文 >> python

python多线程编程(二)--threading模块

zihua 2014-03-15 15:03:28 点击: 785 | 收藏


上一篇文章讲thread模块的使用,我们接下来看threading模块怎么使用。

threading 模块对象

对象

描述

Thread

一个线程的执行对象

Lock

锁对象

RLock

可重入锁对象,使单线程可以再次获得已经获得了的锁(递归锁定)

Condition

条件变量,让一个线程停下来,等待其它线程满足了某个条件

Event

事件对象,通用的条件变量

Semaphore

信号量

BoundedSemaphore

Semaphore 类似,只是它不允许超过初始值

Timer

Thread 相似,不过它要等待一段时间才开始运行

threading Thread 类是最主要的运行对象。

Thread 对象的函数

函数

描述

start()

线程开始执行

run()

线程功能函数

join(timeout=None)

程序挂起,直到线程结束 ; 如果给了 timeout ,则最多阻塞 timeout

getName()

返回线程名字

setName(name)

设置线程名字

isAlive()

这个线程是否还在执行

isDaemon()

返回线程的 daemon 标志

setDaemon(daemonic)

设置线程的 daemon 属性,一定要在调用 start() 函数前调用

使用 Thread 类,我们介绍三种方法来创建线程。

●        创建一个 Thread 的实例,传给它一个函数

●        创建一个 Thread 的实例,传给它一个可调用的类对象

●        Thread 派生出一个子类,创建一个这个子类的实例

下面看第一种, 创建一个 Thread 的实例,传给它一个函数

我们将初始化一个 Thread 对象,把函数(及其参数)传进去。这种方式实例化一个 Thread 与调用 thread.start_new_thread() 之间的最大区别就是,新线程不会立即开始。当你创建线程对象又不想立即开始执行的时候,这是很有用的。

#coding: utf-8
import threading
from time import sleep, ctime

loops = [4,2]

def  loop(nloop, nsec):
	print 'loop', nloop, 'start at:', ctime()
	print 'loop %d 挂起%d秒' % (nloop, nsec)
	sleep(nsec)
	print 'loop', nloop, 'done at:', ctime()

def main():
	print 'main thread start!'
	threads = []  #线程列表
	nloops = range(len(loops))

	for i in nloops:
		t = threading.Thread(target=loop, args=(i, loops[i]))
		threads.append(t)

	for i in nloops:
		threads[i].start()

	for i in nloops:
		threads[i].join()  #等待线程结束

	print 'all done at:', ctime()

if __name__ == '__main__':
	main()

运行结果:


这种方式就省了管理一堆锁的功夫了,只要对每个线程调用 join() 函数,就会等到线程结束。

另外,如果你的主线程除了等线程结束外,还有其它的事情要做(如处理或等待其它的客户请求),那就不用调用 join() 。一旦线程启动后,就会一直运行,直到线程的函数结束,退出为止。所以只有在你要等待线程结束的时候才要调用 join()

第二种方式 ,创建一个 Thread 的实例,传给它一个可调用的类对象

这种方式就是在第一种方式的情况下,将函数封装进类对象里面,由类对象提供功能函数。在创建 Thread 对象时会实例化这个类对象。

#coding: utf-8
import threading
from time import sleep, ctime

loops = [4,2]

class Func(object):
	def __init__(self, func, args, name=""):
		self.name = name
		self.func = func
		self.args =args

	def __call__(self):
		self.res = self.func(*self.args)
		
def  loop(nloop, nsec):
	print 'loop', nloop, 'start at:', ctime()
	print 'loop %d 挂起%d秒' % (nloop, nsec)
	sleep(nsec)
	print 'loop', nloop, 'done at:', ctime()

def main():
	print 'main thread start!'
	threads = []  #线程列表
	nloops = range(len(loops))

	for i in nloops:
		t = threading.Thread(target=Func(loop, (i, loops[i]), loop.__name__))
		threads.append(t)

	for i in nloops:
		threads[i].start()

	for i in nloops:
		threads[i].join()  #等待线程结束

	print 'all done at:', ctime()

if __name__ == '__main__':
	main()

创建新线程的时候, Thread 对象会调用我们的 Func 对象,这时会用到一个特殊函数__call__() 这是 python 的一个特性,只要定义类型的时候,实现 __call__ 函数,这个类型就成为可调用的。 比如实现了 __call__ 函数的 Func 对象实例 instance ,形如 iinstance(arg1,arg2,...) 实际上调用的就是 instance.__call__(arg1,arg2,...)

第三种方式, Thread 派生出一个子类,创建这个子类的实例

#coding: utf-8
import threading
from time import sleep, ctime

loops = [4,2]

class MyThread(threading.Thread):
	def __init__(self, func, args, name=""):
		threading.Thread.__init__(self)
		self.name = name
		self.func = func
		self.args =args

	def run(self):
		self.res = self.func(*self.args)
		
def  loop(nloop, nsec):
	print 'loop', nloop, 'start at:', ctime()
	print 'loop %d 挂起%d秒' % (nloop, nsec)
	sleep(nsec)
	print 'loop', nloop, 'done at:', ctime()

def main():
	print 'main thread start!'
	threads = []
	nloops = range(len(loops))

	for i in nloops:
		t = MyThread(loop, (i, loops[i]), loop.__name__)
		threads.append(t)

	for i in nloops:
		threads[i].start()

	for i in nloops:
		threads[i].join()

	print 'all done at:', ctime()

if __name__ == '__main__':
	main()

这种方式使创建线程对象的代码更简洁。

原文链接:http://www.tuicool.com/articles/67RRJv

作者:zihua | 分类: python | 标签: python | 阅读: 785 | 发布于: 2014-03-15 15时 |