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 2016

2.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 DONE

3. 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 DONE

Python多线程模块的更多相关文章

  1. 用生动的案例一步步带你学会python多线程模块

    鱼和熊掌不可兼得 鱼,我所欲也,熊掌,亦我所欲也,二者不可得兼,舍鱼而取熊掌者也. 从6月开始写公众号,连着四个月一直尽量保证一周五更,结果整天熬夜搞的身体素质骤降.十一休假决定暂时将公众号放放,好好 ...

  2. [python]多线程模块thread与threading

    Python通过两个标准库(thread, threading)提供了对多线程的支持 thread模块 import time import thread def runner(arg): for i ...

  3. 利用python多线程模块实现模拟接口并发

    import requestsimport jsonimport threadingimport timeimport uuid class postrequests(): def __init__( ...

  4. Python多线程及其使用方法

    [Python之旅]第六篇(三):Python多线程及其使用方法   python 多线程 多线程使用方法 GIL 摘要: 1.Python中的多线程     执行一个程序,即在操作系统中开启了一个进 ...

  5. 人人都能学会的 Python 多线程指南~

    大家好鸭!有没有想我~(https://jq.qq.com/?_wv=1027&k=rX9CWKg4) 在 Python 中,多线程最常见的一个场景就是爬虫,例如这样一个需求,有多个结构一样的 ...

  6. Python多线程(threading模块)

    线程(thread)是操作系统能够进行运算调度的最小单位.它被包含在进程之中,是进程中的实际运作单位.一条线程指的是进程中一个单一顺序的控制流,一个进程中可以并发多个线程,每条线程并行执行不同的任务. ...

  7. python threading模块使用 以及python多线程操作的实践(使用Queue队列模块)

    今天花了近乎一天的时间研究python关于多线程的问题,查看了大量源码 自己也实践了一个生产消费者模型,所以把一天的收获总结一下. 由于GIL(Global Interpreter Lock)锁的关系 ...

  8. python 多线程编程之threading模块(Thread类)创建线程的三种方法

    摘录 python核心编程 上节介绍的thread模块,是不支持守护线程的.当主线程退出的时候,所有的子线程都将终止,不管他们是否仍在工作. 本节开始,我们开始介绍python的另外多线程模块thre ...

  9. python笔记9 线程进程 threading多线程模块 GIL锁 multiprocessing多进程模块 同步锁Lock 队列queue IO模型

    线程与进程 进程 进程就是一个程序在一个数据集上的一次动态执行过程.进程一般由程序.数据集.进程控制块三部分组成.我们编写的程序用来描述进程要完成哪些功能以及如何完成:数据集则是程序在执行过程中所需要 ...

随机推荐

  1. 第四期coding_group笔记_用CRF实现分词-词性标注

    一.背景知识 1.1 什么是分词? NLP的基础任务分为三个部分,词法分析.句法分析和语义分析,其中词法分析中有一种方法叫Tokenization,对汉字以字为单位进行处理叫做分词. Example ...

  2. 手动安装windows的磁盘清理工具

    All you really need to do is copy some files that are already located on your server into specific s ...

  3. 快速比较两个uiimage是否相等防止使用原始dsdata造成界面卡顿问题

    UIImage *imageLater = image1; UIImage *imagePre = image2; if (imageLater == imagePre){....}

  4. SD卡操作相关的工具SDCardUtils

    SD卡操作相关的工具 package com.flyou.utils; import java.io.File; import android.os.Environment; import andro ...

  5. Azure Mobile App - Custom Authentication

    Custom Authentication: 1. For OLD Mobile Service - https://azure.microsoft.com/en-us/documentation/a ...

  6. yum安装zabbix监控

    公司的服务器由于没有监控软件监控,最感觉不安全,就开始研究zabbix的安装,最后找到一个最简单的安装方法,在这里记录一下,方便以后的查阅 1.安装zabbix官方的软件配置仓库 rpm -ivh h ...

  7. python(24)- 面向对象进阶

    面向对象基础知识: 1.面向对象是一种编程方式,此编程方式的实现是基于对类和对象的使用: 2.类是一个模板,模板中包装了多个‘函数’供使用(可以将多函数中公用的变量封装到对象中): 3.对象,根据模板 ...

  8. MQTT 测试工具介绍

    eclipse paho 下载地址为: https://repo.eclipse.org/content/repositories/paho-releases/org/eclipse/paho/org ...

  9. PCB板布线中地线和电源线的布线规则

    电源. 地线的布置考虑不周到而引起干扰,使产品的性能下降,严重时会降低产品的成功率.要把电源线和地线处理好,将电源线和地线所产生的噪音干扰降到最低限度,以保证产品的质量.一.电源线和地线的布线规则1) ...

  10. POJ1830开关问题——gauss消元

    题目链接 分析: 第一个高斯消元题目,操作是异或.奇偶能够用0.1来表示,也就表示成bool类型的方程,操作是异或.和加法没有差别 题目中有两个未知量:每一个开关被按下的次数(0.1).每一个开关的转 ...