Thread

先引入一个例子:

>>> from threading import Thread,currentThread,activeCount
>>>
>>> def test(s):
... print "ident:",currentThread().ident
... print "count:",activeCount()
... print s
...
>>>
>>> Thread(target = test, args =('Hello',)).start()
ident: 1099229504
count: 2
Hello

需要模块threading,对应的帮助文档:

http://docs.python.org/2.7/library/threading.html#module-threading

class threading.Thread(group=None, target=None, name=None, args=(), kwargs={})
This constructor should always be called with keyword arguments. Arguments are:
group should be None; reserved for future extension when a ThreadGroup class is implemented.
target is the callable object to be invoked by the run() method. Defaults to None, meaning nothing is called.
name is the thread name. By default, a unique name is constructed of the form “Thread-N” where N is a small decimal number.
args is the argument tuple for the target invocation. Defaults to ().
kwargs is a dictionary of keyword arguments for the target invocation. Defaults to {}. If the subclass overrides the constructor, it must make sure to invoke the base class constructor (Thread.__init__()) before doing anything else to the thread.

除了标识符,还可以给线程取个名字,便于调试。

还可以继承Thread实现自己的线程类:

>>> from threading import *
>>>
>>> class MyThread(Thread):
... def __init__(self,name,*args):
... super(MyThread,self).__init__(name = name)#调用父类的init,设置线程的名称
... self.data = args
...
... def run(self):
... print self.name,self.data
...
>>>
>>> MyThread("abc",range(10)).start()
abc ([0, 1, 2, 3, 4, 5, 6, 7, 8, 9],)>>> >>>
>>> MyThread("abc",range(5)).start()
abc ([0, 1, 2, 3, 4],)
>>> MyThread("abc",range(10)).start()
abc ([0, 1, 2, 3, 4, 5, 6, 7, 8, 9],)

将线程daemon属性设为True,那么表示这是一个背景线程,进程退出时不会等到该线程结束。

调用join()等到线程结束,可提供超时参数(秒,浮点数设定更小粒度)。

isAlive()检查线程状态,join()可以多次调用。

>>> from time import sleep
>>>
>>> def test():
... print "__thread__start__"
... sleep(10)
... print "__thread__exit__"
...
>>>
>>> def run():
... t = Thread(target = test)
... t.start()
... t.join(2) //设置超时时间为2s
...
... print t.isAlive()//检查线程状态
... t.join() //再次等待
...
... print "over!"
...
>>>
>>> run()
__thread__start__
True
__thread__exit__
over!

Lock

Lock不支持递归加锁,也就是说即便在同一个线程中,也必须等待锁释放。通常建议改用RLock,它会处理"owning thread"和"recursion level"状态,对于同一个线程的多次请求锁行为,只累加计数器。每次调用release()将递减该计数器,直到0时释放锁,因此acquire()和relase()必须承兑出现,一个加锁,一个释放。

threading中的成员大多实现了上下文协议,尽可能用with代替手工调用。

>>> lock = RLock()
>>>
>>> def show(i):
... with lock:
... print currentThread().name,i
... sleep(0.1)
...
>>> def test():
... with lock:
... for i in range(5):
... show(i)
...
>>>
>>> for i in range(2):
... Thread(target = test).start()
...
>>>
Thread-2 0
Thread-2 1
Thread-2 2
Thread-2 3
Thread-2 4
Thread-3 0
Thread-3 1
Thread-3 2
Thread-3 3
Thread-3 4

所有线程等待lock锁,串行执行。

Event

Event通过一个内部标记来协调多线程运行。方法wait()阻塞线程执行,直到标记为True。

set()将标记设为True,clear()更改标记为False。isSet()用于判断标记状态。

>>> from threading import *
>>>
>>> def test():
... e = Event()
... def test():
... for i in range(5):
... e.wait()
... e.clear()
... print i
... Thread(target = test).start()
... return e
...
>>> e = test()
>>> e.set()
>>> 0 >>> e.set()
>>> 1 >>> e.set()
>>> 2 >>> e.set()
>>> 3

如果不调用clear(),那么标记一直为True,wait()就不会发生堵塞行为。

通常为每个线程准备一个独立的Event,而不是多个线程共享,以避免未及时调用clear(0时发生意外情况。

condition

condition像Lock和Event的综合体,除基本的锁操作外,还提供了类似yield的功能。

在获取锁以后,可以调用wait()临时让出锁,当前线程被阻塞,直到notify()发送通知后再次请求锁来恢复执行。将wait当做yield,那么notify就是send

可以将已有的锁对象传给Condition

>>> from threading import *
>>> from time import sleep
>>>
>>>
>>> cond = Condition()
>>>
>>> def t1():
... with cond:
... for i in range(5):
... print currentThread().name,i
... sleep(0.1)
... if i == 3:cond.wait()
...
>>>
>>> def t2():
... with cond:
... for i in range(5):
... print currentThread().name,i
... sleep(0.1)
... cond.notify()
...
>>>
>>> Thread(target = t1).start();Thread(target = t2).start()
Thread-1 0
>>> Thread-1 1
Thread-1 2
Thread-1 3 //调用wait(),获取锁,当前线程被阻塞
Thread-2 0
Thread-2 1
Thread-2 2
Thread-2 3
Thread-2 4
Thread-1 4//t2执行完range(5)循环,通过cond.notify()发送通知,重新获取锁,继续执行

只有获取锁的线程才能调用wait()和notify(),因此必须在锁释放前调用。

当wait()释放锁后,其他线程也可进入wait状态。notifyAll()激活所有等待线程,让它们去抢锁然后完成后继续执行。

>>> def test():
... with cond:
... for i in range(5):
... print currentThread().name,i
... sleep(0.1)
... if i == 2:cond.wait()
...
>>>
>>> Thread(target = test).start();Thread(target = test).start()
Thread-3 0 >>> Thread-3 1
Thread-3 2
Thread-4 0
Thread-4 1
Thread-4 2 //Thread-4等待,Thread-3持有锁 >>> with cond:cond.notifyAll() //通知所有cond.wait线程
...
>>> Thread-3 3 //Thread-3和Thread-4再次抢锁完成后继续执行,顺序不定
Thread-3 4
Thread-4 3
Thread-4 4

Semaphore

Semaphore通过一个计数器来限制可同时运行的线程数量。计数器表示还可以运行的线程数量。

acquire()递减计数器,release()则是增加计数器。

>>> sem  = Semaphore(2)
>>>
>>> def test():
... with sem:
... for i in range(5):
... print currentThread().name,i
... sleep(0.1)
...
>>>
>>> for i in range(3):
... Thread(target = test).start()
...
Thread-5 0//线程5和6同时执行,获取计数器,使其减为0,故使得线程7被阻塞
Thread-6 0
>>> Thread-5 1
Thread-6 1
Thread-5 2
Thread-6 2
Thread-5 3
Thread-6 3
Thread-5 4
Thread-6 4//线程5和线程6执行完成后,释放信号量,线程7开始执行
Thread-7 0
Thread-7 1
Thread-7 2
Thread-7 3
Thread-7 4

线程5和6同时执行,获取计数器,使其减为0,故使得线程7被阻塞,故前面输出只有线程5和线程6。

在线程5和线程6执行完成后,释放信号量,线程7开始执行。

Timer

用一个独立线程在n秒后执行某个函数。如定时器尚未执行,可用cancel()取消,定时器仅执行一次。

>>> import datetime
>>> from threading import *
>>>
>>> def test():
... print datetime.datetime.now()
...
>>> Timer(2,test).start()
>>> 2013-10-29 21:28:07.990131

mark:import datetime和from datetime import *

Local

TLS(thread-lock storage)为线程提供独立的存储空间。

>>> from threading import *
>>>
>>> from time import sleep
>>>
>>> data = local()
>>>
>>> def test(fn,x):
... data.x = x
...
... for i in range(5):
... data.x = fn(data.x)
... print currentThread().name,data.x
... sleep(0.1)
...
...
>>>
>>> t1 = (lambda x:x+1,0)
>>> t2 = (lambda x:x+'a','a')
>>>
>>> for d in (t1,t2):
... Thread(target = test,args = d).start()
...
Thread-1 1
Thread-2 aa >>> Thread-1 2
Thread-2 aaa
Thread-1 3
Thread-2 aaaa
Thread-1 4
Thread-2 aaaaa
Thread-1 5
Thread-2 aaaaaa

Python之Threading模块的更多相关文章

  1. python中threading模块详解(一)

    python中threading模块详解(一) 来源 http://blog.chinaunix.net/uid-27571599-id-3484048.html threading提供了一个比thr ...

  2. Python使用Threading模块创建线程

    使用Threading模块创建线程,直接从threading.Thread继承,然后重写__init__方法和run方法: #!/usr/bin/python # -*- coding: UTF-8 ...

  3. 再看python多线程------threading模块

    现在把关于多线程的能想到的需要注意的点记录一下: 关于threading模块: 1.关于 传参问题 如果调用的子线程函数需要传参,要在参数后面加一个“,”否则会抛参数异常的错误. 如下: for i ...

  4. python中threading模块中最重要的Tread类

    Tread是threading模块中的重要类之一,可以使用它来创造线程.其具体使用方法是创建一个threading.Tread对象,在它的初始化函数中将需要调用的对象作为初始化参数传入. 具体代码如下 ...

  5. 学会使用Python的threading模块、掌握并发编程基础

    threading模块 Python中提供了threading模块来实现线程并发编程,官方文档如下: 官方文档 添加子线程 实例化Thread类 使用该方式新增子线程任务是比较常见的,也是推荐使用的. ...

  6. Python之threading模块的使用

    作用:同一个进程空间并发运行多个操作,专业术语简称为:[多线程] 1.任务函数不带参数多线程 #!/usr/bin/env python # -*- coding: utf-8 -*- import ...

  7. Python(多线程threading模块)

    day27 参考:http://www.cnblogs.com/yuanchenqi/articles/5733873.html CPU像一本书,你不阅读的时候,你室友马上阅读,你准备阅读的时候,你室 ...

  8. python中threading模块中的Join类

    join类是threading中用于堵塞当前主线程的类,其作用是阻止全部的线程继续运行,直到被调用的线程执行完毕或者超时.具体代码如下: import threading,time def doWai ...

  9. Python中threading模块的join函数

    Join的作用是阻塞进程直到线程执行完毕.通用的做法是我们启动一批线程,最后join这些线程结束,例如: for i in range(10): t = ThreadTest(i) thread_ar ...

随机推荐

  1. #云栖大会# 移动安全专场——APP渠道推广作弊攻防那些事儿(演讲速记)

    导语: 如今,移动互联网浪潮进入白热化竞争态势,APP渠道传播成为很多企业常用的推广方式,APP推广费用也在水涨船高,从PC时代的一个装机0.5元到1元不等,到移动互联网时代的5元,甚至几十元,但为什 ...

  2. CSS盒子模型之详解

    前言:        盒子模型是css中最核心的基础知识,理解了这个重要的概念才能更好的排版,进行页面布局.一.css盒子模型概念    CSS盒子模型 又称框模型 (Box Model) ,包含了元 ...

  3. 【学习】ie-css3.htc---让ie8以下支持css3

    学习了偶象大神的一篇文章:<让IE6/IE7/IE8浏览器支持CSS3属性>http://www.zhangxinxu.com/wordpress/?p=783 亲自实践了一下,主要是bo ...

  4. linux 远程操作(expect)

    Expect是在Tcl基础上创建起来的,它还提供了一些Tcl所没有的命令,它可以用来做一些linux下无法做到交互的一些命令操作,在远程管 理方面发挥很大的作用. spawn命令激活一个Unix程序来 ...

  5. EL&&JSTL

    一.JSP技术 1.jsp脚本和注释 jsp脚本: 1)<%java代码%> ----- 内部的java代码翻译到service方法的内部 2)<%=java变量或表达式> - ...

  6. JS难点--面向对象(封装)

    我觉得js的难点之一就是面向对象编程. 面向对象 它是一种编程思想,它在写法上比面向过程相对来说复杂一些: 以下是我学习中关于面向对象的知识点总结:   1.什么是对象 从广义上说,"一切皆 ...

  7. Nginx-OpenResty安装配置

    上两篇中介绍了: Ngnix技术研究系列1-通过应用场景看Nginx的反向代理 Ngnix技术研究系列2-基于Redis实现动态路由 发现,应该加一篇OpenResty的安装部署说明,方便大家按图索骥 ...

  8. Java基础总结--多线程总结1

    ----进程和线程-----1.概述:简单理解一个进程就是一个正在运行的程序(程序在内存中的所属空间)程序只有在运行的时候才会被加载进内存2.进程内部的划分进程不会直接执行,只是被当作分配内存资源的基 ...

  9. 小技巧:Oracle:sqlplus 显示行列字符数

    遇到这种情况可以判断:行显示字符数不够,可以增加行显示字符数 01.可以当前会话HR@ACE >set line 400; 02.上面的方法其它会话不生效,懒不想每次设置怎么办? Oracle: ...

  10. Linux系列教程(八)——Linux常用命令之压缩和解压缩命令

    前面一篇博客我们讲解了Linux帮助和用户管理命令,对于帮助命令,man 命令能获得命令和配置文件的帮助信息,help命令能获得shell内置命令的帮助信息.我们可以通过which来区分什么是shel ...