Python中使用线程的一些可行方法

受益于在此的讨论:http://stackoverflow.com/questions/2846653/how-to-use-threading-in-python

另外一篇了解Python内线程机制的交好blog: https://jeffknupp.com/blog/2012/03/31/pythons-hardest-problem/

1、使用 threading module:

适用范围:

适用于建立那些与I/O操作相关的操作线程。

因为CPython并不真正在多个core上并发执行多个CPU密集型(CPU-bound)的线程。使用threading.Thread class来建立的线程在真正执行时,受限于Python 解释器的全局锁,只能串行地在CPU上进行执行即使我们的CPU上有多个core充分支持多线程并发执行。但是对于某些包含有重I/O操作的进程中,我们可以使用threading来建立线程,然后由它来单独等待i/o操作(网络数据或disk数据)完成,此时将cpu资源释放出来交由主程序线程继续执行,因此整体起到了让主程序线程不被i/o阻塞的作用。

应用实例:

实例一:

import Queue

import threading

import urllib2

# 每个新建线程所调用的执行函数

def get_url(q, url):

q.put(urllib2.urlopen(url).read())

theurls = ["http://google.com", "http://yahoo.com"]

q = Queue.Queue() #Queue在内部实现的时候就是线程安全的,所以在使用它的时候不需考虑锁、条件变量、事件及信息量等多线程间执行协调因子

for u in theurls:

t = threading.Thread(target=get_url, args = (q,u))

# 将每个新建的线程设为daemon模式,这样当主线程结束后,新建的子线程可继续执行

t.daemon = True #

t.start()

s = q.get()

print s

2、真正的并发执行-使用multiprocessing:

适用范围:

适用于需要fork出多个进程,然后执行真正的多core CPU之上并发执行的程序。

multiprocessing module可以fork出多个真正并发执行的进程。由于全局解释器锁的原因,使用threading模块只能交替执行其建立的多个线程,而这只有在有i/o操作阻塞需要绕过的时候才能发挥较好的作用。。

应用实例:

实例一:

from multiprocessing import Process

def f(name):

print 'hello', name

if __name__ == '__main__':

p = Process(target=f, args=('bob',))

p.start()

p.join()

这个小程序创建了一个进程,让它运行起来。主程序在将它启动起来后,又使用join方法等待它执行结束退出,然后回收它。此后主进程才会退出,程序执行完成。如果我们不在程序的最后使用join来等待子进程执行结束,那么主进程退出后,子进程有可能尚未退出,这会导致它成为一个僵尸进程,资源无法得到有效回收。

3、使用multiprocessing.dummy中的Pool或者直接使用multiprocessing.Pool(关于multiprocessing.dummy的区别,可由官方文档上的说明而知。‘multiprocessing.dummy replicates the API of multiprocessing but is no more than a wrapper around the threading module.’)

通过使用map与Pool来生成多个具有相同目标函数的并发线程。其中map是函数式编程的一个常用函数,另一个是reduce。

实例一:

from multiprocessing.dummy import Pool as ThreadPool

pool = ThreadPool(4)

results = pool.map(my_function, my_array)

它是由如下单线程程序改进而得的多线程程序。

results = []

for item in my_array:

results.append(my_function(item))

实例二:

import urllib2

from multiprocessing.dummy import Pool as ThreadPool

urls = [

'http://www.python.org',

'http://www.python.org/about/',

'http://www.onlamp.com/pub/a/python/2003/04/17/metaclasses.html',

'http://www.python.org/doc/',

'http://www.python.org/download/',

'http://www.python.org/getit/',

'http://www.python.org/community/',

'https://wiki.python.org/moin/',

]

# 在各个线程内部调用同一个目标运行函数'urllib2.urlopen',但是传入不同的参数,进而在这些线程中返回不同的值

with Pool(4) as pool:

results = pool.map(urllib2.urlopen, urls)

#当然也可使用多个数组作为参数,如下所示

results = pool.starmap(function, zip(list_a, list_b))

#或者也可以向下面这样使用一个常量与数组作为参数,如下所示

results = pool.starmap(function, zip(itertools.repeat(constant), list_a))

4、结合threading, multiprocessing, subprocess进行的多进程并发

利用threading来建立多个交叉执行的线程,然后在每个线程中执行由subprocess直接启动的可在shell下执行的进程。

import Queue

import threading

import multiprocessing

import subprocess

q = Queue.Queue()

for i in range(30): #将我们要执行的30个任务放入队列当中

q.put(i)

def worker():

while True:

item = q.get()

#执行一个任务,调用shell程序,在下面执行我们的task,然后等待它结束返回

subprocess.call("echo "+str(item), shell=True)

q.task_done()

cpus=multiprocessing.cpu_count() #获得我们系统中所具有的可执行cpu核的数目

print("Creating %d threads" % cpus)

for i in range(cpus):

t = threading.Thread(target=worker)

t.daemon = True

t.start()

q.join() #队列阻塞直到所有task被执行完毕

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 212,185评论 6 493
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,445评论 3 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 157,684评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,564评论 1 284
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,681评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,874评论 1 290
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,025评论 3 408
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,761评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,217评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,545评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,694评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,351评论 4 332
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,988评论 3 315
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,778评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,007评论 1 266
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,427评论 2 360
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,580评论 2 349

推荐阅读更多精彩内容

  • 本文是笔者学习廖雪峰Python3教程的笔记,在此感谢廖老师的教程让我们这些初学者能够一步一步的进行下去.如果读者...
    相关函数阅读 5,515评论 1 8
  • 1.进程 1.1多线程的引入 现实生活中 有很多的场景中的事情是同时进行的,比如开车的时候手和脚共同来驾驶汽车,再...
    TENG书阅读 497评论 0 0
  • 多任务可以由多进程完成,也可以由一个进程内的多线程完成。我们前面提到了进程是由若干线程组成的,一个进程至少有一个线...
    壁花烧年阅读 813评论 0 0
  • 目录 一、开启线程的两种方式 在python中开启线程要导入threading,它与开启进程所需要导入的模块mul...
    CaiGuangyin阅读 2,400评论 1 16
  • 个人笔记,方便自己查阅使用 Py.LangSpec.Contents Refs Built-in Closure ...
    freenik阅读 67,682评论 0 5