`
crazier9527
  • 浏览: 1013827 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类
最新评论

Python多线程编程

阅读更多

我们在做软件开发的时候很多要用到多线程技术。例如如果做一个下载软件象flashget就要用到、象在线视频工具realplayer也要用到因为要同时下载media stream还要播放。其实例子是很多的。

线程相对进程来说是“轻量级”的,操作系统用较少的资源创建和管理线程。程序中的线程在相同的内存空间中执行,并共享许多相同的资源。

python中如何创建一个线程对象

如果你要创建一个线程对象,很简单,只要你的类继承threading.Thread,然后在__init__里首先调用threading.Thread__init__方法即可

import threading
class mythread(threading.Thread):
def __init__(self, threadname):
threading.Thread.__init__(self, name = threadname)
….

这才仅仅是个空线程,我可不是要他拉空车的,他可得给我干点实在活。很简单,重写类的run()方法即可,把你要在线程执行时做的事情都放到里面

import threading
import time
class mythread(threading.Thread):
def __init__(…):
….
def run(self):
for i in range(10):
print self.getName, i
time.sleep(1)

以上代码我们让这个线程在执行之后每隔1秒输出一次信息到屏幕,10次后结束

getName()threading.Thread类的一个方法,用来获得这个线程对象的name。还有一个方法setName()当然就是来设置这个线程对象的name的了。

如果要创建一个线程,首先就要先创建一个线程对象

mythread1 = mythread(’mythread 1′)

一个线程对象被创建后,他就处于“born”(诞生状态)

如何让这个线程对象开始运行呢?只要调用线程对象的start()方法即可

mythread1.start()

现在线程就处于“ready”状态或者也称为“runnable”状态。

奇怪吗?不是已经start了吗?为什么不称为“running”状态呢?其实是有原因的。因为我们的计算机一般是不具有真正并行处理能力的。我们所谓的多线程只是把时间分成片段,然后隔一个时间段就让一个线程执行一下,然后进入“sleeping ”状态,然后唤醒另一个在“sleeping”的线程,如此循环runnable->sleeping->runnable… ,只是因为计算机执行速度很快,而时间片段间隔很小,我们感受不到,以为是同时进行的。所以说一个线程在start了之后只是处在了可以运行的状态,他什么时候运行还是由系统来进行调度的。

那一个线程什么时候会“dead”呢?一般来说当线程对象的run方法执行结束或者在执行中抛出异常的话,那么这个线程就会结束了。系统会自动对“dead”状态线程进行清理。

如果一个线程t1在执行的过程中需要等待另一个线程t2执行结束后才能运行的话那就可以在t1在调用t2join()方法

….
def t1(…):

t2.join()

这样t1在执行到t2.join()语句后就会等待t2结束后才会继续运行。

但是假如t1是个死循环的话那么等待就没有意义了,那怎么办呢?可以在调用t2join()方法的时候给一个浮点数做超时参数,这样这个线程就不会等到花儿也谢了了。我等你10s,你不回来我还不允许我改嫁啊? :)

def t1(…):

t2.join(10)

如果一个进程的主线程运行完毕而子线程还在执行的话,那么进程就不会退出,直到所有子线程结束为止,如何让主线程结束的时候其他子线程也乖乖的跟老大撤退呢?那就要把那些不听话的人设置为听话的小弟,使用线程对象的setDaemon()方法,参数为bool型。True的话就代表你要听话,我老大(主线程)扯呼,你也要跟着撤,不能拖后腿。如果是False的话就不用那么听话了,老大允许你们将在外军命有所不受的。需要注意的是setDaemon()方法必须在线程对象没有调用start()方法之前调用,否则没效果。

t1 = mythread(’t1′)
print t1.getName(),t1.isDaemon()
t1.setDaemon(True)
print t1.getName(),t1.isDaemon()
t1.start()
print ‘main thread exit’

当执行到 print ‘main thread exit’ 后,主线程就退出了,当然t1这个线程也跟着结束了。但是如果不使用t1线程对象的setDaemon()方法的话,即便主线程结束了,还要等待t1线程自己结束才能退出进程。isDaemon()是用来获得一个线程对象的Daemonflag状态的。

如何来获得与线程有关的信息呢?

获得当前正在运行的线程的引用

running = threading.currentThread()

获得当前所有活动对象(即run方法开始但是未终止的任何线程)的一个列表

threadlist = threading.enumerate()

获得这个列表的长度

threadcount = threading.activeCount()

查看一个线程对象的状态调用这个线程对象的isAlive()方法,返回1代表处于“runnable”状态且没有“dead

threadflag = threading.isAlive()

Python线程编程(二)简单的线程同步

多个执行线程经常要共享数据,如果仅仅读取共享数据还好,但是如果多个线程要修改共享数据的话就可能出现无法预料的结果。

假如两个线程对象t1t2都要对数值num=0进行增1运算,那么t1t2都各对num修改10次的话,那么num最终的结果应该为20。但是如果当t1取得num的值时(假如此时num0),系统把t1调度为“sleeping”状态,而此时t2转换为“running”状态,此时t2获得的num的值也为0,然后他把num+1的值1赋给num。系统又把t2转化为“sleeping”状态,t1为“running”状态,由于t1已经得到num值为0,所以他也把num+1的值赋给了num1。本来是2次增1运行,结果却是num只增了1次。类似这样的情况在多线程同时执行的时候是有可能发生的。所以为了防止这类情况的出现就要使用线程同步机制。

最简单的同步机制就是“锁”

锁对象用threading.RLock类创建

mylock = threading.RLock()

如何使用锁来同步线程呢?线程可以使用锁的acquire() (获得)方法,这样锁就进入“locked”状态。每次只有一个线程可以获得锁。如果当另一个线程试图获得这个锁的时候,就会被系统变为“blocked”状态,直到那个拥有锁的线程调用锁的release() (释放)方法,这样锁就会进入“unlocked”状态。“blocked”状态的线程就会收到一个通知,并有权利获得锁。如果多个线程处于“blocked”状态,所有线程都会先解除“blocked”状态,然后系统选择一个线程来获得锁,其他的线程继续沉默(“blocked”)。

import threading
mylock = threading.RLock()
class mythread(threading.Thread)

def run(self …):
…     #此处 不可以 放置修改共享数据的代码
mylock.acquire()
…     #此处 可以 放置修改共享数据的代码
mylock.release()
#此处 不可以 放置修改共享数据的代码

我们把修改共享数据的代码称为“临界区”,必须将所有“临界区”都封闭在同一锁对象的acquire()release()方法调用之间。

锁只能提供最基本的同步级别。有时需要更复杂的线程同步,例如只在发生某些事件时才访问一个临界区(例如当某个数值改变时)。这就要使用“条件变量”。

条件变量用threading.Condition类创建

mycondition = threading.Condition()

条件变量是如何工作的呢?首先一个线程成功获得一个条件变量后,调用此条件变量的wait()方法会导致这个线程释放这个锁,并进入“blocked”状态,直到另一个线程调用同一个条件变量的notify()方法来唤醒那个进入“blocked”状态的线程。如果调用这个条件变量的notifyAll()方法的话就会唤醒所有的在等待的线程。

如果程序或者线程永远处于“blocked”状态的话,就会发生死锁。所以如果使用了锁、条件变量等同步机制的话,一定要注意仔细检查,防止死锁情况的发生。对于可能产生异常的临界区要使用异常处理机制中的finally子句来保证释放锁。等待一个条件变量的线程必须用notify()方法显式的唤醒,否则就永远沉默。保证每一个wait()方法调用都有一个相对应的notify()调用,当然也可以调用notifyAll()方法以防万一。

Python线程编程(三)同步队列

我 们经常会采用生产者/消费者关系的两个线程来处理一个共享缓冲区的数据。例如一个生产者线程接受用户数据放入一个共享缓冲区里,等待一个消费者线程对数据 取出处理。但是如果缓冲区的太小而生产者和消费者两个异步线程的速度不同时,容易出现一个线程等待另一个情况。为了尽可能的缩短共享资源并以相同速度工作 的各线程的等待时间,我们可以使用一个“队列”来提供额外的缓冲区。

创建一个“队列”对象

import Queue
myqueue = Queue.Queue(maxsize = 10)
Queue.Queue类即是一个队列的同步实现。队列长度可为无限或者有限。可通过Queue的构造函数的可选参数maxsize来设定队列长度。如果maxsize小于1就表示队列长度无限。

 

将一个值放入队列中

myqueue.put(10)

调用队列对象的put()方法在队尾插入一个项目。put()有两个参数,第一个item为必需的,为插入项目的值;第二个block为可选参数,默认为1。如果队列当前为空且block1put()方法就使调用线程暂停,直到空出一个数据单元。如果block0put方法将引发Full异常。

将一个值从队列中取出

myqueue.get()

调用队列对象的get()方法从队头删除并返回一个项目。可选参数为block,默认为1。如果队列为空且block1get()就使调用线程暂停,直至有项目可用。如果block为0,队列将引发Empty异常。

我们用一个例子来展示如何使用Queue# queue_example.py
from Queue import Queue
import threading
import random
import time

 

# Producer thread
class Producer(threading.Thread):
def __init__(self, threadname, queue):
threading.Thread.__init__(self, name = threadname)
self.sharedata = queue
def run(self):
for i in range(20):
print self.getName(),’adding’,i,’to queue’
self.sharedata.put(i)
time.sleep(random.randrange(10)/10.0)
print self.getName(),’Finished’

# Consumer thread
class Consumer(threading.Thread):
def __init__(self, threadname, queue):
threading.Thread.__init__(self, name = threadname)
self.sharedata = queue
def run(self):
for i in range(20):
print self.getName(),’got a value:’,self.sharedata.get()
time.sleep(random.randrange(10)/10.0)
print self.getName(),’Finished’

# Main thread
def main():
queue = Queue()
producer = Producer(’Producer’, queue)
consumer = Consumer(’Consumer’, queue)

print ‘Starting threads …’
producer.start()
consumer.start()

producer.join()
consumer.join()

print ‘All threads have terminated.’

if __name__ == ‘__main__’:
main()

示例代码中实现了两个类:生产者类Producer和消费者类Consumer。前者在一个随机的时间内放入一个值到队列queue中然后显示出来,后者在一定随机的时间内从队列queue中取出一个值并显示出来。

分享到:
评论

相关推荐

    Python 多线程编程实例

    Python 多线程编程实例,一个综合示例

    Python多线程编程(6寸)[归纳].pdf

    Python多线程编程是利用Python实现程序并行性的一种方式,尤其适合于处理异步、并发事务和资源密集型任务。在多线程环境中,多个线程可以同时执行,提高程序效率,尤其对于那些需要从多个输入源处理数据或者进行大量...

    python 多线程编程

    通过分析和学习这个文件,你可以进一步加深对Python多线程编程的理解,包括如何有效地使用线程池(`ThreadPoolExecutor`),以及如何处理线程异常和线程间的协作问题。 总之,Python的多线程编程虽然受到GIL的限制...

    Python多线程编程.zip

    Python多线程编程.zipPython多线程编程.zipPython多线程编程.zipPython多线程编程.zipPython多线程编程.zipPython多线程编程.zipPython多线程编程.zipPython多线程编程.zipPython多线程编程.zip 运行python的时候,...

    python多线程编程实现网络串口透传

    Python多线程编程在实现网络串口透传中扮演着重要的角色,特别是在处理TCP客户端网口数据时。网络串口透传技术允许通过网络连接模拟串行通信,使得远程设备可以像连接本地串口一样进行通信。这在物联网(IoT)、远程...

    python多线程编程.rar

    Python多线程编程是Python系统编程中的重要组成部分,它允许程序同时执行多个任务,从而提高程序的效率和响应速度。在Python中,我们通常使用内置的`thread`库、`threading`库以及`Queue`库来实现多线程。 首先,`...

    第20章 Python多线程编程.pdf

    Python多线程编程是一种允许程序同时执行多个线程的技术,以实现程序的并行处理。这通常适用于那些可以分解为多个独立任务的程序,其中各个任务之间能够并发执行,从而提高程序的效率和响应速度。 在操作系统中,...

    Python多线程编程简单介绍

    Python多线程编程是Python标准库中的一个强大功能,它允许程序员在程序中运行多个线程,实现多任务处理。这一功能主要通过Python的`threading`模块实现。本文将详细介绍如何在Python中使用多线程,包括创建线程、`...

    Python多线程编程的实践指南.docx

    尽管文档标题与内容存在不一致(标题提及了“Python多线程编程的实践指南”而内容却涉及到了Matlab),这里我们将聚焦于Python多线程编程的相关知识点展开详细讨论。 ### Python多线程编程的实践指南 #### 一、多...

    Python多线程编程篇教程(实例).PDF

    ### Python多线程编程知识点详解 #### 一、线程状态与类型 在开始深入探讨Python多线程编程之前,我们需要先理解线程的基本概念及其生命周期。线程在其生命周期内会经历多种状态,主要包括以下几种: 1. **New ...

    Python多线程编程(6寸)[借鉴].pdf

    Python多线程编程是软件开发中一种重要的技术,它允许程序员同时执行多个任务,提高程序的效率和响应速度。在Python中,多线程是通过`thread`和`threading`模块来实现的。 1. **线程和进程的区别** - **进程**:是...

    Python多线程编程详细示例

    这个是在学习python多线程的时候自己总结的文档,对理解Python多线程非常有帮助,很多都是从官方文档而来的。

    python多线程编程示例(threading.py)

    1、多线程的理解 多进程和多线程都可以执行多个任务,线程是进程的一部分。...2、Python多线程创建 在Python中,同样可以实现多线程,有两个标准模块thread和threading,不过我们主要使用 更高级的threading模块。

    Python多线程编程方式2 threading库的介绍源码

    在阅读源码时,可以重点关注`Thread`类的构造方法、`start`、`run`、`join`等方法,以及同步对象如`Lock`的实现,这有助于理解Python多线程的工作原理。 总的来说,`threading`库是Python中进行多线程编程的主要...

    python之多线程编程1

    Python 多线程编程基础 Python 多线程编程是 Python 编程语言中的一种重要概念。通过多线程编程,Python 开发者可以同时执行多个任务,从而提高程序的执行效率和响应速度。在本文中,我们将介绍 Python 中的多线程...

    在Python下尝试多线程编程

    在Python中进行多线程编程是计算机编程领域一个非常重要的课题。多线程编程在提高程序执行效率、...以上内容仅为对Python多线程编程知识点的概述,要真正掌握和应用这些知识,还需要通过实际的编程实践和深入的学习。

    Python技术如何进行多线程编程.docx

    #### 二、Python多线程编程的基本原理 Python中的多线程编程主要依赖于`threading`模块。该模块提供了`Thread`类用于创建和管理线程,使开发者能够轻松实现并发执行的功能。 - **线程创建与启动**:在Python中创建...

    Python多线程编程之多线程加锁操作示例

    本文实例讲述了Python多线程编程之多线程加锁操作。分享给大家供大家参考,具体如下: Python语言本身是支持多线程的,不像PHP语言。 下面的例子是多个线程做同一批任务,任务总是有task_num个,每次线程做一个任务...

Global site tag (gtag.js) - Google Analytics