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. shell细节决定高度

    1.文件测试操作符 -f[file]:文件存在且为普通文件则为真; -d[directory]:文件存在且为目录文件则为真; -s[size]:文件存在且为文件大小不为0则为真; -e[exist]: ...

  2. Oracle PL/SQL块 多表查询(emp员工表、dept部门表、salgrade工资等级表)

    范例: 查询每个员工的编号,姓名,职位,工资,工资等级,部门名称 ●确定要使用的数据表 |- emp表:员工的编号.姓名.职位.工资 |- salgrade表:工资等级 |- dept表:部门名称 ● ...

  3. servlet跳转页面后图片不显示

    我是用图片的相对路径,原先直接打开jsp的话图片是可以正常显示的,通过servlet跳转之后图片就显示不出来了 后来发现是图片路径的问题, 我是将图片放在WebRoot里面自己创建的img中,原先图片 ...

  4. DNA的复制

    半保留复制 DNA分子复制时, DNA分子的双螺旋将解开, 互补的碱基之间的氢键断裂, 解开的两条单链作为复制的模板, 游离的脱氧核苷酸依据碱基互补配对的原则, 通过形成氢键结合到作为模板的单链上. ...

  5. XSY1659 [HNOI2012]永无乡

    题面 Description 永无乡包含 n 座岛,编号从 1 到 n. 每座岛都有自己的独一无二的重要度,按照重要度可以将这n座岛排名,名次用 1到n来表示.某些岛之间由巨大的桥连接,通过桥可以从一 ...

  6. Linux下使用mv重命名文件或者移动文件(增强版的工具为rename)

    mv命令既可以重命名,又可以移动文件或文件夹. 例子:将目录A重命名为B mv A B 例子:将/a目录移动到/b下,并重命名为c mv /a /b/c 例子:将文件A.txt重命名为B.txt mv ...

  7. 我们为什么要把Dagger2,MVP以及Rxjava引入项目中?

    1Why? 我们为什么要把Dagger2,MVP以及Rxjava引入项目中? 毫无疑问在Android开发圈中这三个技术是经常被提及的,如此多的文章和开源项目在介绍他们,使用他们,开发者也或多或少的被 ...

  8. SSH错误:packet_write_wait: Connection to 10.57.19.250 port 22: Broken pipe

    现象:ssh连接以后,服务器会主动断开连接,wireshark抓包,发线服务器会tcp rst,断开ssh连接 解决尝试:1.修改会话超时时间:2.客户端主动间隔性向服务器发送保活报文:3.服务端主动 ...

  9. 为了安全,linux下如何使用某个用户启动某个进程?

    安全里有个原则,叫最小权限原则 根据这个原则,对于启动某个应用或者进程,应该赋予其最小权限,根据应用权限要求,创建一个相应权限的用户,赋予其应用相应的权限,然后使用这个用户启用这个应用 如何使用某个用 ...

  10. 6.【nuxt起步】-完成一个静态的页面

    1.接下来新建/component/maincontent.vue 把这些html代码copy到maincontent.vue 发现格式比较难看,就格式化一下 2.插件安装 beautify,安装后重 ...