设为首页 收藏本站
查看: 1410|回复: 0

[经验分享] Python多线程编程

[复制链接]

尚未签到

发表于 2015-4-22 12:13:02 | 显示全部楼层 |阅读模式
1.全局解释器锁定
      Python虚拟机使用GIL(Global Interpreter Lock,全局解释器锁定)来互斥线程对共享资源的访问,暂时无法利用多处理器的优势。虽然python解释器可以“运行”多个线程,但在任意时刻,不管有多少的处理器,任何时候都总是只有一个线程在执行。对于I/O密集型任务,使用线程一般是没有问题的,而对于涉及大量CPU计算的应用程序而言,使用线程来细分工作没有任何好处,用户最好使用子进程和消息传递。

2.threading
  python的threading模块提供Thread类和各种同步原语,用于编写多线程的程序。
  2.1. Thread(target=None,name=None,args=(),kwargs={})
  此函数创建一个Thread实例。target是一个可调用函数,线程启动时,run()方法将调用此对象。name是线程的名称,默认是'Thread-N'的格式。args是传递给target函数的参数元组,kwargs是传递给target函数的关键字参数的字典。
  Thread实例t支持以下方法和属性:


  • t.start()                 启动线程,就是调用run()方法
  • t.run()                   可以在Thread的子类中重新定义
  • t.join([timeout])      阻塞当前上下文环境的线程,直到调用此方法的线程终止或到达指定的timeout(可选参数)。
  • t.is_live()                返回线程的活动状态
  • t.name                   线程的名称
  • t.ident                    线程标识符
  • t.daemon                设置线程是否为守护线程,必须在t.start()前设置。当设置为True时,主线程要退出时,不必等守护线程完成。'
  创建线程有两种方法:


  • 创建一个Thread实例,传递给它一个函数



import threading
import time
def clock(nsec):
whhile True:
print 'Now is %s'%time.ctime()
time.sleep(nsec)
t=threading.Thread(target=clock,args=(5,))
t.daemon=True  #设置为守护线程
t.start()
  2. 从Thread派生出一个子类,然后创建一个子类的实例



import threading
import time
class ClockThread(threading.Thread):
def __init__(self,nsec):
threading.Thread.__init__(self)
self.daemon=True   #设置为守护线程
self.nsec=nsec
def run():
while True:
print 'Now is s%'%time.ctime()
time.sleep(self.nsec)
t=ClockThread(5)
t.start()
  后一种方法比较python一点。
  由于线程会无限循环,所以设置daemonTrue,这样当进程结束时,线程也将被销毁。
  例如有个数数程序,一个线程从1数到9,另一个线程从a数到j,每个线程都要耗费9s,如果要顺序执行的话需耗费18s。



import threading
import time
class CountThread(threading.Thread):
def __init__(self,func,name):
threading.Thread.__init__(self)
self.name=str(name)
self.func=func
def run(self):
apply(self.func)
def numcount():
print threading.currentThread().name,'start at : ',time.ctime()
for i in range(10):
print i
time.sleep(1)
print threading.currentThread().name,'done at : ',time.ctime()
def alphacount():
print threading.currentThread().name,'start at : ',time.ctime()
for i in range(97,107):
print chr(i)
time.sleep(1)
print threading.currentThread().getName(),'done at : ',time.ctime()
def main():
funclist=[numcount,alphacount]
threads=[]
for i in funclist:
t=CountThread(i,i.__name__)
threads.append(t)
for t in threads:
t.start()
for t in threads:
t.join()
print 'All done at :',time.ctime()
if __name__=='__main__':
main()
  结果:



numcount  start at :    Fri Feb 07 12:19:28
alphacount  start at : Fri Feb 07 12:19:28 2014
a0
b1
2c
3d
4
e
5f
6g
7
h
8
i
9j
alphacount numcount  done at :  done at : Fri Feb 07 12:19:38 2014
Fri Feb 07 12:19:38 2014
All done at : Fri Feb 07 12:19:38 2014
  10s就完成了。
  举一个更清晰的看t.join()作用的例子:



import threading
import time
def join():
print 'in Threadjoin'
time.sleep(1)
print 'out Threadjoin'
Threadjoin=threading.Thread(target=join,name='Threadjoin')
def context(Threadjoin):
print 'in Threadcontext'
Threadjoin.start()
Threadjoin.join()   #Threadjoin线程开始阻塞,等待Threadjoin完成
print 'out Threadcontext'
Threadcontext=threading.Thread(target=context,name='Threadcontext',args=(Threadjoin,))
Threadcontext.start()

  结果:



>>>
in Threadcontext
in Threadjoin
out Threadjoin
out Threadcontext

2.2. 线程的同步
  线程运行在创建它的进程内部,共享所有的数据和资源,但都有自己独立的栈和堆。编写并发编程的难点在于同步和访问共享数据。多个任务同时更新一个数据结构可能导致数据损坏和程序状态不一致(也就是竞争条件)。要解决这个问题,必须找出程序的关键代码段,并使用互斥锁和其它类似的同步手段保护他们。
  2.2.1 Lock
  原语锁定(互斥锁定)是一个同步原语,状态是"已锁定"或"未锁定"之一。两个方法acquire()和release()用于修改锁定的状态。如果有多个线程在等待获取锁定,当锁定释放时,只有一个线程能获得它。
  构造方法:
Lock()  :创建新的Lock对象,初始状态为未锁定
  实例方法:
Lock.acquire([timeout]): 使线程进入同步阻塞状态,尝试获得锁定。 成功获取锁定返回True,无法获取锁定返回False。
Lock.release(): 释放锁。使用前线程必须已获得锁定,否则将抛出异常。
  Python多线程分块读取大文件:



import threading
import os
seekposition=0
blocksize=1000000
filesize=0
def getFilesize(filename):
f=open(filename)
f.seek(0,os.SEEK_END)
filesize=f.tell()
f.close()
return filesize
def parsefile(filename):
global seekposition,filesize
f=open(filename)
while True:
lock.acquire()   #seekposition是线程共享的,修改时需要锁定
startposition=seekposition
endposition=(startposition+blocksize) if (startposition+blocksize)0:
f.seek(startposition)
f.readline()    #分成的block第一行可能不是完整的一行,略掉不处理,而是作为上一个block的最后一行处理
position=f.tell()
outfile=open(str(endposition)+'.txt','w')
while position

运维网声明 1、欢迎大家加入本站运维交流群:群②:261659950 群⑤:202807635 群⑦870801961 群⑧679858003
2、本站所有主题由该帖子作者发表,该帖子作者与运维网享有帖子相关版权
3、所有作品的著作权均归原作者享有,请您和我们一样尊重他人的著作权等合法权益。如果您对作品感到满意,请购买正版
4、禁止制作、复制、发布和传播具有反动、淫秽、色情、暴力、凶杀等内容的信息,一经发现立即删除。若您因此触犯法律,一切后果自负,我们对此不承担任何责任
5、所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其内容的准确性、可靠性、正当性、安全性、合法性等负责,亦不承担任何法律责任
6、所有作品仅供您个人学习、研究或欣赏,不得用于商业或者其他用途,否则,一切后果均由您自己承担,我们对此不承担任何法律责任
7、如涉及侵犯版权等问题,请您及时通知我们,我们将立即采取措施予以解决
8、联系人Email:admin@iyunv.com 网址:www.yunweiku.com

所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其承担任何法律责任,如涉及侵犯版权等问题,请您及时通知我们,我们将立即处理,联系人Email:kefu@iyunv.com,QQ:1061981298 本贴地址:https://www.yunweiku.com/thread-59612-1-1.html 上篇帖子: Selenium-解决使用Webdrive打开Firefox不含有插件的问题(python) 下篇帖子: Selenium Python bindings 文档二
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

扫码加入运维网微信交流群X

扫码加入运维网微信交流群

扫描二维码加入运维网微信交流群,最新一手资源尽在官方微信交流群!快快加入我们吧...

扫描微信二维码查看详情

客服E-mail:kefu@iyunv.com 客服QQ:1061981298


QQ群⑦:运维网交流群⑦ QQ群⑧:运维网交流群⑧ k8s群:运维网kubernetes交流群


提醒:禁止发布任何违反国家法律、法规的言论与图片等内容;本站内容均来自个人观点与网络等信息,非本站认同之观点.


本站大部分资源是网友从网上搜集分享而来,其版权均归原作者及其网站所有,我们尊重他人的合法权益,如有内容侵犯您的合法权益,请及时与我们联系进行核实删除!



合作伙伴: 青云cloud

快速回复 返回顶部 返回列表