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. VS2010 c/c++ 本地化 emscripten 配置

    配置环境 1.下载emsdk-1.35.0-full-64bit.exe,有VS2010的话直接安装. 2.安装好之后,打开cmd,# emsdk update # emsdk install lat ...

  2. (转)Python-正则表达式

    在前面我们已经搞定了怎样获取页面的内容,不过还差一步,这么多杂乱的代码夹杂文字我们怎样把它提取出来整理呢?下面就开始介绍一个十分强大的工具,正则表达式! 1.了解正则表达式 正则表达式是对字符串操作的 ...

  3. [bzoj2131]免费的馅饼 树状数组优化dp

    2131: 免费的馅饼 Time Limit: 10 Sec  Memory Limit: 259 MB[Submit][Status][Discuss] Description Input 第一行是 ...

  4. PyCharm 2017 官网 下载 安装 设置 配置 (主题 字体 字号) 使用 入门 教程

    一.安装 Python 3.6 首先,要安装好 Python 3.6.如果你还没有安装,可以参考咪博士之前的教程 Python 3.6.3 官网 下载 安装 测试 入门教程 (windows) 二.官 ...

  5. (10.23)Java小知识!

    ---恢复内容开始--- 方法的定义: 一般情况下,定义一个方法包含以下语法: 修饰符 返回值类型 方法名 (参数类型 参数名 , ...){ ... 方法体 ... return 返回值; } 修饰 ...

  6. go基础编程 day-2

    Go的常亮 关键字: Const Go常亮的多个定义: // 定义常亮的关键字 const // 定义多个常亮 const( PI = 3.14 const1 = " const2 = co ...

  7. APP在模拟器崩溃,提示__gcd_queue_item_enqueue_hook_block_invoke

    libBacktraceRecording.dylib`__gcd_queue_item_enqueue_hook_block_invoke: libBacktraceRecording.dylib` ...

  8. Thrift - 快速入门

    简单实例 有homebrew的话,直接执行以下命令即可,brew会处理相关依赖(https://thrift.apache.org/docs/install/). brew install thrif ...

  9. LeetCode 381. Insert Delete GetRandom O(1) - Duplicates allowed (插入删除和获得随机数 常数时间 允许重复项)

    Design a data structure that supports all following operations in average O(1) time. Note: Duplicate ...

  10. LeetCode 226. Invert Binary Tree (反转二叉树)

    Invert a binary tree. 4 / \ 2 7 / \ / \ 1 3 6 9 to 4 / \ 7 2 / \ / \ 9 6 3 1 Trivia:This problem was ...