threading.Thread
Thread 是 threading 模块中最重要的类之一,可用于创建线程。创建线程有两种方式:一种是继承Thread类,重写其run方法;另一种是创建一个threading.Thread对象,并将可调用对象作为参数传递给它的初始化函数(__init__)。进入。下面给出例子。
先来看看通过继承threading.Thread类来创建线程的例子:
#coding=gbk
import threading, time, random
count = 0
class Counter(threading.Thread):
def __init__(self, lock, threadName):
'''@summary: 初始化对象。
@param lock: 琐对象。
@param threadName: 线程名称。
'''
super(Counter, self).__init__(name = threadName)
#注意:一定要显式的调用父类的初始化函数。
self.lock = lock
def run(self):
'''@summary: 重写父类run方法,在线程启动后执行该方法内的代码。
'''
global count
self.lock.acquire()
for i in xrange(10000):
count = count + 1
self.lock.release()
lock = threading.Lock()
for i in range(5):
Counter(lock, "thread-" + str(i)).start()
time.sleep(2)
#确保线程都执行完毕
print count
在代码中,我们创建了一个继承 threading.Thread 的 Counter 类。初始化函数接收两个参数,一个是普通对象,另一个是线程名。在 Counter 中,继承自父类的 run 方法被重写,run 方法将一个全局变量一一递增 10000。
在下面的代码中,创建了五个 Counter 对象,并分别调用了它们的 start 方法。最后打印结果。这里我们解释一下run方法和start方法:它们都是继承自Thread,线程启动后会执行run()方法,相关逻辑可以写到run方法中(通常是调用run方法一个活动[活动]。); start() 方法用于启动线程。
再看看另外一种创建线程的方法:
import threading, time, random
count = 0
lock = threading.Lock()
def doAdd():
'''@summary: 将全局变量count 逐一的增加10000。
'''
global count, lock
lock.acquire()
for i in xrange(10000):
count = count + 1
lock.release()
for i in range(5):
threading.Thread(target = doAdd, args = (), name = 'thread-' + str(i)).start()
time.sleep(2)
#确保线程都执行完毕
print count
在这段代码中,我们定义了 doAdd 方法,它将全局变量 count 逐个递增 10000。然后,创建了五个Thread对象,将函数对象doAdd作为参数传递给它的初始化函数,然后调用Thread对象的start方法。线程启动后,会执行doAdd函数。有必要介绍一下threading.Thread类的初始化函数原型:
def __init__(self, group=None, target=None, name=None, args=(), kwargs={})
参数group是预留的,用于将来扩展;
参数target是一个可调用对象(也称为activity[activity]),在线程启动后执行;
参数name是线程的名字。默认值为“Thread-N“,N是一个数字。
参数args和kwargs分别代表调用target时的参数列表和关键字参数。
Thread类还定义了以下常用方法与属性:
Thread.getName()
Thread.setName()
Thread.name
用于获取和设置线程的名称。
Thread.ident
获取线程的标识符。线程标识符是一个非零整数,该属性只有在调用start()方法后才有效,否则只返回None。
Thread.is_alive()
Thread.isAlive()
确定线程是否处于活动状态(活着)。线程从调用 start() 方法启动线程开始一直处于活动状态,直到 run() 方法完成执行或遇到未处理的异常并被中断。
Thread.join([timeout])
调用 Thread.join 将阻塞调用线程,直到被调用线程完成运行或超时。参数 timeout 为数值类型,表示超时时间。如果不提供此参数,则调用线程将被阻塞,直到被调用线程结束。以下示例说明了 join() 的用法:
import threading, time
def doWaiting():
print 'start waiting:', time.strftime('%H:%M:%S')
time.sleep(3)
print 'stop waiting', time.strftime('%H:%M:%S')
thread1 = threading.Thread(target = doWaiting)
thread1.start()
time.sleep(1)
#确保线程thread1已经启动
print 'start join'
thread1.join()
#将一直堵塞,直到thread1运行结束。
print 'end join'
threading.RLock和threading.Lock
在 threading 模块中,定义了两种类型的锁:threading.Lock 和 threading.RLock。它们之间存在细微差别,通过比较以下两段代码来说明:
import threading
lock = threading.Lock()
#Lock对象
lock.acquire()
lock.acquire()
#产生了死琐。
lock.release()
lock.release()
import threading
rLock = threading.RLock()
#RLock对象
rLock.acquire()
rLock.acquire()
#在同一线程内,程序不会堵塞。
rLock.release()
rLock.release()
两种锁的主要区别在于 RLock 允许在同一个线程中进行多次获取。锁不允许这样做。注意:如果使用RLock,acquire和release必须成对出现,即如果acquire被调用n次,release必须被调用n次才能真正释放被占用的琐事。
threading.Condition
条件可以理解为高级的琐碎,它提供了比Lock和RLock更高级的功能,可以让我们控制复杂的线程同步问题。 threadiong.Condition 内部维护了一个 trivial 对象(默认为 RLock),可以在创建 Condigtion 对象时作为参数传入。 Condition 还提供了acquire 和release 方法,与普通的acquire 和release 方法含义相同。其实就是简单的调用了内部平凡对象的对应方法。 Condition还提供了以下方法(请注意:这些方法只能在获取后调用,否则会报RuntimeError异常):
Condition.wait([timeout]):
wait 方法释放内部占用的杂务,线程被挂起,直到被通知唤醒或超时(如果提供了超时参数)。当线程被唤醒并重新占用时,程序将继续执行。
Condition.notify():
唤醒一个挂起的线程(如果有挂起的线程)。注意: notify() 方法不会释放占用的杂务。
Condition.notify_all()
Condition.notifyAll()
唤醒所有挂起的线程(如果有任何挂起的线程)。注意:这些方法不会释放占用的杂务。
现在写一个捉迷藏游戏,专门介绍threading.Condition的基本使用。假设这个游戏由两个人玩,一个隐藏(Hider),另一个寻找(Seeker)。游戏规则如下: 1、游戏开始后,Seeker先蒙上眼睛,蒙上眼睛后通知Hider; 2、Hider收到通知后,开始找地方躲起来。隐藏后,他通知 Seeker 可以 3. Seeker 收到通知后,开始寻找 Hider。 Hider 和 Seeker 都是独立的个体,在程序中由两个独立的线程表示。在游戏过程中,两者的行为具有一定的时间关系。我们通过Condition来控制这个时序关系。
#---- Condition
#---- 捉迷藏的游戏
import threading, time
class Hider(threading.Thread):
def __init__(self, cond, name):
super(Hider, self).__init__()
self.cond = cond
self.name = name
def run(self):
time.sleep(1)
#确保先运行Seeker中的方法
self.cond.acquire()
#b
print self.name + ': 我已经把眼睛蒙上了'
self.cond.notify()
self.cond.wait()
#c
#f
print self.name + ': 我找到你了 ~_~'
self.cond.notify()
self.cond.release()
#g
print self.name + ': 我赢了'
#h
class Seeker(threading.Thread):
def __init__(self, cond, name):
super(Seeker, self).__init__()
self.cond = cond
self.name = name
def run(self):
self.cond.acquire()
self.cond.wait()
#a #释放对琐的占用,同时线程挂起在这里,直到被notify并重新占
有琐。
#d
print self.name + ': 我已经藏好了,你快来找我吧'
self.cond.notify()
self.cond.wait()
#e
#h
self.cond.release()
print self.name + ': 被你找到了,哎~~~'
cond = threading.Condition()
seeker = Seeker(cond, 'seeker')
hider = Hider(cond, 'hider')
seeker.start()
hider.start()
threading.Event
Event 实现了与 Condition 类似的功能,但比 Condition 简单一些。它通过维护内部标识符来解决线程之间的同步问题。 (threading.Event 与 .NET 中的 System.Threading.ManualResetEvent 类做同样的事情。)
Event.wait([timeout])
阻塞线程,直到 Event 对象的内部标志设置为 True 或超时(如果提供了参数 timeout)。
Event.set()
将标识位设为Ture
Event.clear()
将标识伴设为False。
Event.isSet()
判断标识位是否为Ture。
下面使用Event来实现捉迷藏的游戏(用Event来实现可能不是很形象)
#---- Event
#---- 捉迷藏的游戏
import threading, time
class Hider(threading.Thread):
def __init__(self, cond, name):
super(Hider, self).__init__()
self.cond = cond
self.name = name
def run(self):
time.sleep(1)
#确保先运行Seeker中的方法
print self.name + ': 我已经把眼睛蒙上了'
self.cond.set()
time.sleep(1)
self.cond.wait()
print self.name + ': 我找到你了 ~_~'
self.cond.set()
print self.name + ': 我赢了'
class Seeker(threading.Thread):
def __init__(self, cond, name):
super(Seeker, self).__init__()
self.cond = cond
self.name = name
def run(self):
self.cond.wait()
print self.name + ': 我已经藏好了,你快来找我吧'
self.cond.set()
time.sleep(1)
self.cond.wait()
print self.name + ': 被你找到了,哎~~~'
cond = threading.Event()
seeker = Seeker(cond, 'seeker')
hider = Hider(cond, 'hider')
seeker.start()
hider.start()
threading.Timer
threading.Timer 是 threading.Thread 的子类,可以在指定的时间间隔后执行操作。这是 Python 手册中的一个示例:
def hello():
print "hello, world"
t = Timer(3, hello)
t.start()
# 3秒钟之后执行hello函数。
threading模块中还有一些常用的方法没有介绍:
threading.active_count()
threading.activeCount()
获取当前活动的(alive)线程的个数。
threading.current_thread()
threading.currentThread()
获取当前的线程对象(Thread object)。
threading.enumerate()
获取当前所有活动线程的列表。
threading.settrace(func)
设置一个跟踪函数,用于在run()执行之前被调用。
threading.setprofile(func)
设置一个跟踪函数,用于在run()执行完毕之后调用。
threading模块的内容很多。
本文为原创文章,版权归知行编程网所有,欢迎分享本文,转载请保留出处!
你可能也喜欢
- ♥ 如何在python中使用sum函数09/04
- ♥ python是否支持重载10/27
- ♥ python中二叉树的类型有哪些12/13
- ♥ Python endswith() 方法12/19
- ♥ python下载的包在哪里09/17
- ♥ 如何在python中换行09/21
内容反馈