Python多线程模块
0. 引言
在Python中可使用的多线程模块主要有两个,thread和threading模块。thread模块提供了基本的线程和锁的支持,建议新手不要使用。threading模块允许创建和管理线程,提供了更多的同步原语。
1. thread
thread模块函数:
- start_new_thread(function, args[, kwargs])
- 启动新的线程以执行function,返回线程标识。
- allocate_lock()
- 返回LockType对象。
- exit()
- 抛出SystemExit异常,如果没有被捕获,线程静默退出。
LockType类型锁对象的方法:
- acquire([waitflag])
- 无参数,无条件获得锁,如果锁已经被其他线程获取,则等待锁被释放。如果使用整型参数,参数为0,如果锁可获取,则获取且返回True,否则返回False;参数为非0,与无参数相同。
- locked()
- 返回锁的状态,如果已经被获取,则返回True,否则返回False。
- release()
- 释放锁。只有已经被获取的锁才能被释放,不限于同一个线程。
#!/usr/bin/env python
# -*- coding: utf-8 -*-
import thread
from time import ctime
from time import sleep
loops = [4, 2]
def loop0():
    print 'start loop 0 at:', ctime()
    sleep(4)
    print 'loop 0 done at:', ctime()
def loop1():
    print 'start loop 1 at:', ctime()
    sleep(2)
    print 'loop 1 done at:', ctime()
def loop(nloop, nsec, lock):
    print 'start loop', nloop, 'at:', ctime()
    sleep(nsec)
    print 'loop', nloop, 'done at:', ctime()
    lock.release()
def main():
    print 'starting  at:', ctime()
    loop0()
    loop1()
    print 'all DONE at:', ctime()
def main1():
    print 'starting at:', ctime()
    thread.start_new_thread(loop0, ())
    thread.start_new_thread(loop1, ())
    sleep(6)
    print 'all DONE at:', ctime()
def main2():
    print 'starting at:', ctime()
    locks = []
    nloops = range(len(loops))
    for i in nloops:
        lock = thread.allocate_lock()
        lock.acquire()
        locks.append(lock)
    for i in nloops:
        print thread.start_new_thread(loop, (i, loops[i], locks[i]))
    for i in nloops:
        while locks[i].locked():
            pass
    print 'all DONE at:', ctime()
if __name__ == '__main__':
    #main()
    #main1()
    main2()2. threading
threading模块提供了更好的线程间的同步机制。threading模块下有如下对象:
- Thread
- Lock
- RLock
- Condition
- Event
- Semaphore
- BoundedSemaphore
- Timer
threading模块内还有如下的函数:
- active_count()
- activeCount() 
 - 返回当前alive的线程数量
 
- Condition() 
 - 返回新的条件变量对象
 
- current_thread()
- currentThread() 
 - 返回当前线程对象
 
- enumerate() 
 - 返回当前活动的线程,不包括已经结束和未开始的线程,包括主线程及守护线程。
 
- settrace(func) 
 - 为所有线程设置一个跟踪函数。
 
- setprofile(func) 
 - 为所有纯种设置一个profile函数。
 
2.1 Thread
类Thread有如下属性和方法:
- Thread(group=None, target=None, name=None, args=(), kwargs={})
- start()
- run()
- join([timeout])
- name
- getName()
- setName(name)
- ident
- is_alive()
- isAlive()
- daemon
- isDaemon()
- setDaemon(daemonic)
创建线程一般有如下三种方法: 
1. 传递函数创建Thread实例。  
2. 传递可调用类的实例创建Thread实例。 
3. 从Thread派生出一个子类,创建一个子类实例。
2.1.1 下面使用threading模块实现与上面相同的功能:
#!/usr/bin/env python
# -*- coding: utf-8 -*-
import threading
from time import ctime
from time import sleep
loops = [4, 2]
def loop(nloop, nsec):
    print 'start loop', nloop, 'at:', ctime()
    sleep(nsec)
    print 'loop', nloop, 'done at:', ctime()
def main():
    print 'starting at:', ctime()
    threads = []
    nloops = range(len(loops))
    for i in nloops:
        t = threading.Thread(target=loop, args=(i, loops[i]))
        threads.append(t)
    for i in nloops:
        threads[i].start()
    for i in nloops:
        threads[i].join()
    print 'all DONE at:', ctime()
if __name__ == '__main__':
    main()
程序输出如下:
starting at: Fri Jul 15 15:56:25 2016
start loop 0 at: Fri Jul 15 15:56:25 2016
start loop 1 at: Fri Jul 15 15:56:25 2016
loop 1 done at: Fri Jul 15 15:56:27 2016
loop 0 done at: Fri Jul 15 15:56:29 2016
all DONE at: Fri Jul 15 15:56:29 20162.1.2 在创建新线程时,还可以给Thread传递可调用类的对象,这样使用类本身来保存信息, 如:
#!/usr/bin/env python
# -*- coding: utf-8 -*-
import threading
from time import ctime
from time import sleep
loops = [4, 2]
class ThreadFunc(object):
    def __init__(self, func, args, name=''):
        self.name = name
        self.func = func
        self.args = args
    def __call__(self):
        apply(self.func, self.args)
def loop(nloop, nsec):
    print 'start loop', nloop, 'at:', ctime()
    sleep(nsec)
    print 'loop', nloop, 'done at:', ctime()
def main():
    print 'starting at:', ctime()
    threads = []
    nloops = range(len(loops))
    for i in nloops:
        t = threading.Thread(target=ThreadFunc(loop, (i, loops[i]),
                                               loop.__name__))
        threads.append(t)
    for i in nloops:
        threads[i].start()
    for i in nloops:
        threads[i].join()
    print 'all DONE at:', ctime()
if __name__ == '__main__':
    main()程序的输出与上面的是一致的。
2.1.3 从Thread派生一个子类,然后创建这个子类的实例
#!/usr/bin/env python
# -*- coding: utf-8 -*-
import threading
from time import ctime
from time import sleep
loops = [4, 2]
class MyThread(threading.Thread):
    def __init__(self, func, args, name=''):
        threading.Thread.__init__(self)
        self.name = name
        self.func = func
        self.args = args
    def run(self):
        apply(self.func, self.args)
def loop(nloop, nsec):
    print 'start loop', nloop, 'at:', ctime()
    sleep(nsec)
    print 'loop', nloop, 'done at:', ctime()
def main():
    print 'starting at:', ctime()
    threads = []
    nloops = range(len(loops))
    for i in nloops:
        t = MyThread(loop, (i, loops[i]), loop.__name__)
        threads.append(t)
    for i in nloops:
        threads[i].start()
    for i in nloops:
        threads[i].join()
    print 'all DONE at:', ctime()
if __name__ == '__main__':
    main()
程序运行结果与上面也是一样的。
2.1.4 实例
现在将MyThread单独放在一个模块内,就叫myThread:
#!/usr/bin/env python
# -*- coding: utf-8 -*-
import threading
from time import ctime
class MyThread(threading.Thread):
    def __init__(self, func, args, name=''):
        threading.Thread.__init__(self)
        self.name = name
        self.func = func
        self.args = args
    def run(self):
        print 'starting', self.name, 'at', ctime()
        self.res = apply(self.func, self.args)
        print self.name, 'finished at:', ctime()
    def getResult(self):
        return self.res
if __name__ == '__main__':
    pass现在要计算阶乘、求和、fibinacci。由于计算时间不同,添加适当的sleep()进行时间上控制。
#!/usr/bin/env python
# -*- coding: utf-8 -*-
from myThread import MyThread
from time import ctime
from time import sleep
def fib(x):
    sleep(0.005)
    if x < 2:
        return 1
    return fib(x - 1) + fib(x - 2)
def fac(x):
    sleep(0.1)
    if x < 2:
        return 1
    return x * fac(x - 1)
def sum_c(x):
    sleep(0.1)
    if x < 2:
        return 1
    return x + sum_c(x - 1)
def main():
    nfuncs = range(len(funcs))
    print '*** SINGLE THREAD'
    for i in nfuncs:
        print 'starting', funcs[i].__name__, 'at:', ctime()
        print funcs[i](n)
        print funcs[i].__name__, 'finished at:', ctime()
    print '\n*** MULTIPLE THREADS'
    threads = []
    for i in nfuncs:
        t = MyThread(funcs[i], (n,), funcs[i].__name__)
        threads.append(t)
    for i in nfuncs:
        threads[i].start()
    for i in nfuncs:
        threads[i].join()
        print threads[i].getResult()
    print 'all DONE'
funcs = [fib, fac, sum_c]
n = 12
if __name__ == '__main__':
    main()结果如下:
*** SINGLE THREAD
starting fib at: Fri Jul 15 17:48:02 2016
233
fib finished at: Fri Jul 15 17:48:04 2016
starting fac at: Fri Jul 15 17:48:04 2016
479001600
fac finished at: Fri Jul 15 17:48:05 2016
starting sum_c at: Fri Jul 15 17:48:05 2016
78
sum_c finished at: Fri Jul 15 17:48:07 2016
*** MULTIPLE THREADS
starting fib at Fri Jul 15 17:48:07 2016
starting fac at Fri Jul 15 17:48:07 2016
starting sum_c at Fri Jul 15 17:48:07 2016
fac finished at: Fri Jul 15 17:48:08 2016
sum_c finished at: Fri Jul 15 17:48:08 2016
fib finished at: Fri Jul 15 17:48:09 2016
233
479001600
78
all DONE3. Queue
Queue模块可以用来线程间通讯,让各个线程之间共享数据。通过Queue模块的工厂方法Queue(maxsize=0)创建Queue对象,maxsize指定了队列的大小,默认为无限大小。对象Queue属性如下:
- qsize()
- 返回队列的大小。
 
- empty() 
 - 如果队列为空,返回True,否则返回False。
 
- full() 
 - 如果队列已满,返回True,否则返回False。
 
- put(item[, block[, timeout]]) 
 - 把item放入队列
 
- get([block[, timeout]]) 
 - 从队列头部取出一个对象
 
#!/usr/bin/env python
# -*- coding: utf-8 -*-
from myThread import MyThread
from Queue import Queue
from random import randint
from time import sleep
def writeQ(queue):
    print 'producing object for Q...',
    queue.put('xxx', 1)
    print 'size now', queue.qsize()
def readQ(queue):
    val = queue.get(1)
    print 'consumed object from Q... size now', queue.qsize()
def writer(queue, loops):
    for i in range(loops):
        writeQ(queue)
        sleep(randint(1, 3))
def reader(queue, loops):
    for i in range(loops):
        readQ(queue)
        sleep(randint(2, 5))
funcs = [writer, reader]
nfuncs = range(len(funcs))
def main():
    nloops = randint(2, 5)
    q = Queue(32)
    threads = []
    for i in nfuncs:
        t = MyThread(funcs[i], (q, nloops), funcs[i].__name__)
        threads.append(t)
    for i in nfuncs:
        threads[i].start()
    for i in nfuncs:
        threads[i].join()
    print 'all DONE'
if __name__ == '__main__':
    main()可能运行结果为:
starting writer at Mon Jul 18 10:59:13 2016
producing object for Q... size now 1
starting reader at Mon Jul 18 10:59:13 2016
consumed object from Q... size now 0
producing object for Q... size now 1
consumed object from Q... size now 0
producing object for Q... size now 1
writer finished at: Mon Jul 18 10:59:19 2016
consumed object from Q... size now 0
reader finished at: Mon Jul 18 10:59:24 2016
all DONEPython多线程模块的更多相关文章
- 用生动的案例一步步带你学会python多线程模块
		鱼和熊掌不可兼得 鱼,我所欲也,熊掌,亦我所欲也,二者不可得兼,舍鱼而取熊掌者也. 从6月开始写公众号,连着四个月一直尽量保证一周五更,结果整天熬夜搞的身体素质骤降.十一休假决定暂时将公众号放放,好好 ... 
- [python]多线程模块thread与threading
		Python通过两个标准库(thread, threading)提供了对多线程的支持 thread模块 import time import thread def runner(arg): for i ... 
- 利用python多线程模块实现模拟接口并发
		import requestsimport jsonimport threadingimport timeimport uuid class postrequests(): def __init__( ... 
- Python多线程及其使用方法
		[Python之旅]第六篇(三):Python多线程及其使用方法 python 多线程 多线程使用方法 GIL 摘要: 1.Python中的多线程 执行一个程序,即在操作系统中开启了一个进 ... 
- 人人都能学会的 Python 多线程指南~
		大家好鸭!有没有想我~(https://jq.qq.com/?_wv=1027&k=rX9CWKg4) 在 Python 中,多线程最常见的一个场景就是爬虫,例如这样一个需求,有多个结构一样的 ... 
- Python多线程(threading模块)
		线程(thread)是操作系统能够进行运算调度的最小单位.它被包含在进程之中,是进程中的实际运作单位.一条线程指的是进程中一个单一顺序的控制流,一个进程中可以并发多个线程,每条线程并行执行不同的任务. ... 
- python threading模块使用 以及python多线程操作的实践(使用Queue队列模块)
		今天花了近乎一天的时间研究python关于多线程的问题,查看了大量源码 自己也实践了一个生产消费者模型,所以把一天的收获总结一下. 由于GIL(Global Interpreter Lock)锁的关系 ... 
- python 多线程编程之threading模块(Thread类)创建线程的三种方法
		摘录 python核心编程 上节介绍的thread模块,是不支持守护线程的.当主线程退出的时候,所有的子线程都将终止,不管他们是否仍在工作. 本节开始,我们开始介绍python的另外多线程模块thre ... 
- python笔记9 线程进程  threading多线程模块  GIL锁  multiprocessing多进程模块 同步锁Lock   队列queue  IO模型
		线程与进程 进程 进程就是一个程序在一个数据集上的一次动态执行过程.进程一般由程序.数据集.进程控制块三部分组成.我们编写的程序用来描述进程要完成哪些功能以及如何完成:数据集则是程序在执行过程中所需要 ... 
随机推荐
- hdu6217(数学)
			题意: 你需要输出在16进制下,π的第n位的数字 分析: 既然要求第n位的数字,我们不妨把原来的数字乘上$16^{n-1}$,我们要求的就是这个和式的小数部分的最高位 我们可以用double暴力求出小 ... 
- Java 浅析,生成OFD文件
			摘要:这几天遇到个需要,需要提供用户下载电子证照,最简单的方法实现:word做了一份模板,利用网页工具转成OFD文件,http://www.yozodcs.com/page/example.html用 ... 
- Redis安装过程
			Redis在windows下安装过程 学习了:https://www.cnblogs.com/M-LittleBird/p/5902850.html 学习了:http://www.runoob.com ... 
- Hibernate调试——定位查询源头
			本文是我在importNew翻译的文章,首发在importNew,这里会定期更新链接. 为什么有时Hibernate会在程序某一部分生成一条指定sql查询?这个问题让人非常难立马理解.当处理不是我们本 ... 
- 安装mongoDB遇见的一个路径问题
			如果安装路径不存在,则不会解压EXE软件! 安装monogoDB后,它不会自动添加执行路径! 意思就是安装路径是D盘下面的mongoDB文件夹,假如不存在这个文件夹,则不会安装成功 你需要添加路径: ... 
- 设计模式之中介者模式(Mediator)摘录
			23种GOF设计模式一般分为三大类:创建型模式.结构型模式.行为模式. 创建型模式抽象了实例化过程.它们帮助一个系统独立于怎样创建.组合和表示它的那些对象.一个类创建型模式使用继承改变被实例化的类,而 ... 
- Android多线程下载大文件解析
			1.多线程介绍 用过迅雷的同学都知道.迅雷有个功能叫做多线程.另一个叫离线下载,我们这里重点介绍一下多线程下载.多线程,顾名思义就是非常多歌线程同一时候在执行,为什么要提出多线程这个概念呢?由于有时候 ... 
- hdu5296(2015多校1)--Annoying problem(lca+一个公式)
			Annoying problem Time Limit: 16000/8000 MS (Java/Others) Memory Limit: 65536/65536 K (Java/Others ... 
- diff patch
			http://rails-deployment.group.iteye.com/group/wiki/1318-diff-and-patch-10-minutes-guide 情景一:你正尝试从代码编 ... 
- 修改mysql数据库 密码
			将密码改成123456 update mysql.user set authentication_string=password('123456') where user='root' and Hos ... 
