python中threading多线程
python中有两个处理多线程的模块thread和threading。其中thread提供了多线程底层支持的模块,以低级原始的发那个是来处理和控制线程,使用起来较为复杂;而threading基于thread进行包装,将线程操作对象化。
最基础的的多线程
我们先看一个最最基础的多线程例子
- import threading
- import time
- class test(threading.Thread):
- def __init__(self,name,delay):
- threading.Thread.__init__(self)
- self.name = name
- self.delay = delay
- def run(self):
- print "%s is running"%self.name
- for x in range(self.delay):
- time.sleep(1)
- print "%s is saying hello %d"%(self.name,x)
- def main():
- t1 = test('Thread 1',3)
- t2 = test('Thread 2',2)
- t1.start()
- t2.start()
- if __name__ == '__main__':
- main()
- print "End of main"
输出结果如下:
Thread 1 is running
End of mainThread 2 is runningThread 1 is saying hello 0
Thread 2 is saying hello 0
Thread 1 is saying hello 1
Thread 2 is saying hello 1
Thread 1 is saying hello 2
可以看出Thread1 和Thread2基本上轮流执行的,这就是多线程的好处,否则如果顺序执行2个程序会需要2倍的时间。
start是对thread的run()的封装,在调用start()的时候,会执行run()函数。
如果把代码中的一段改成下面这样呢?
- def main():
- t1 = test('Thread 1',3)
- t2 = test('Thread 2',2)
- t1.start()
- print "wait for thread1 end"
- t1.join()
- t2.start()
输出结果为:
wait for thread1 endThread 1 is running
Thread 1 is saying hello 0
Thread 1 is saying hello 1
Thread 1 is saying hello 2
End of mainThread 2 is runningThread 2 is saying hello 0
Thread 2 is saying hello 1
从上面可以看出,调用了t1.join()后,t2会一直等到t1执行完毕才会开始执行。
使用Queue进行多线程编程
使用线程队列
如前所述,当多个线程需要共享数据或者资源的时候,可能会使得线程的使用变得复杂。线程模 块提供了许多同步原语,包括信号量、条件变量、事件和锁。当这些选项存在时,最佳实践是转而关注于使用队列。相比较而言,队列更容易处理,并且可以使得线 程编程更加安全,因为它们能够有效地传送单个线程对资源的所有访问,并支持更加清晰的、可读性更强的设计模式。
- import threading
- import time
- import Queue
- import urllib2
- import os
- class test(threading.Thread):
- def __init__(self,queue):
- threading.Thread.__init__(self)
- self.queue = queue
- def run(self):
- while 1:
- url = self.queue.get()
- print self.name+"begin download"+url+"..."
- self.download(url)
- self.queue.task_done()
- print self.name+"download completed"
- def download(self,url):
- urlHandle = urllib2.urlopen(url)
- with open(os.path.basename(url)+".html","wb")as fp:
- while 1:
- contents=urlHandle.read(1024)
- if not contents:
- break
- else:
- fp.write(contents)
- def main():
- ulrs = ["http://wiki.python.org/moin/Webprograming",
- "https://www.baidu.com",
- "http://wiki.python.org/moin/Documendation"]
- q = Queue.Queue(5)
- for each in ulrs:
- q.put(each)
- for i in range(5):
- t = test(q)
- t.setDaemon(True)
- t.start()
- q.join()
- if __name__ == '__main__':
- main()
join()
保持阻塞状态,直到处理了队列中的所有项目为止。在将一个项目添加到该队列时,未完成的任务的总数就会增加。当使用者线程调用 task_done() 以表示检索了该项目、并完成了所有的工作时,那么未完成的任务的总数就会减少。当未完成的任务的总数减少到零时,
join()
就会结束阻塞状态。
每个线程运行的时候就从队列里get一个url,这时候队列的长度就缩小1,然后完成的时候发送通知。直到队列为空的时候表示全部执行完毕。
调试的时候发现即使不要task_done()也可以得到一样的结果。但是主线程会一直阻塞着无法继续执行,所以task_done的任务是告诉主线程的当前任务完成了,并递减未完成的任务数,这样主线程才知道什么时候所有的任务都完成了,好继续执行。
使用线程池
可以自己实现一个线程池模块,也可以用已经存在的第三方线程池库,本文用的是后者,比较简单。
首先安装一个threadpool的库
- pip install threadpool
然后用下面的代码完成和使用Queue一样的功能
- import urllib2
- import os
- import threadpool
- def download(url):
- urlHandle = urllib2.urlopen(url)
- with open(os.path.basename(url)+".html","wb")as fp:
- while 1:
- contents=urlHandle.read(1024)
- if not contents:
- break
- else:
- fp.write(contents)
- def main():
- ulrs = ["http://wiki.python.org/moin/Webprograming",
- "https://www.baidu.com",
- "http://wiki.python.org/moin/Documendation"]
- thread_num=5
- pool = threadpool.ThreadPool(thread_num)
- requests = threadpool.makeRequests(download,ulrs)
- print "put all request to thread pool"
- for each in requests:
- pool.putRequest(each)
- pool.poll() # 处理任务队列中新的请求
- pool.wait() # 阻塞用于等待所有执行结果
- print "destroy all threads"
- pool.dismissWorkers(thread_num,do_join=True)
- if __name__ == '__main__':
- main()
python中threading多线程的更多相关文章
- python中threading模块详解(一)
python中threading模块详解(一) 来源 http://blog.chinaunix.net/uid-27571599-id-3484048.html threading提供了一个比thr ...
- python中的多线程【转】
转载自: http://c4fun.cn/blog/2014/05/06/python-threading/ python中关于多线程的操作可以使用thread和threading模块来实现,其中th ...
- Python中的多线程编程,线程安全与锁(二)
在我的上篇博文Python中的多线程编程,线程安全与锁(一)中,我们熟悉了多线程编程与线程安全相关重要概念, Threading.Lock实现互斥锁的简单示例,两种死锁(迭代死锁和互相等待死锁)情况及 ...
- python中的多线程
一个程序可以理解为一个进程,这个进程有其代号,可以依据这个代号将其杀死. 一个进程肯定有且只有一个主线程,他可以有很多子线程. 运行一个任务如果可以有许多子线程同时去做,当然会提高效率. 但是,在py ...
- python中的多线程和多进程
一.简单理解一下线程和进程 一个进程中可有多个线程,线程之间可共享内存,进程间却是相互独立的.打比方就是,进程是火车,线程是火车厢,车厢内人员可以流动(数据共享) 二.python中的多线程和多进程 ...
- python中threading的用法
摘自:http://blog.chinaunix.net/uid-27571599-id-3484048.html 以及:http://blog.chinaunix.net/uid-11131943- ...
- 2016/1/2 Python中的多线程(1):线程初探
---恢复内容开始--- 新年第一篇,继续Python. 先来简单介绍线程和进程. 计算机刚开始发展的时候,程序都是从头到尾独占式地使用所有的内存和硬件资源,每个计算机只能同时跑一个程序.后来引进了一 ...
- Python中的多线程编程,线程安全与锁(一)
1. 多线程编程与线程安全相关重要概念 在我的上篇博文 聊聊Python中的GIL 中,我们熟悉了几个特别重要的概念:GIL,线程,进程, 线程安全,原子操作. 以下是简单回顾,详细介绍请直接看聊聊P ...
- Python之threading多线程,多进程
1.threading模块是Python里面常用的线程模块,多线程处理任务对于提升效率非常重要,先说一下线程和进程的各种区别,如图 概括起来就是 IO密集型(不用CPU) 多线程计算密集型(用CPU) ...
随机推荐
- WordPress常用标签和调用总结
调用头部模板<?php get_header();?> 调用尾部模板<?php get_footer();?> 调用侧边栏<?php get_sidebar();?> ...
- ios代码实现时间设置NSDate
本文转载至 http://www.baidu.com/link?url=dcQWiL1FD_She6P4RM2IvEeJas0_gtG3LkRNTV5H87X0AyKCHvwYjBz2hdcB2JVp ...
- Android开发:《Gradle Recipes for Android》阅读笔记(翻译)2.4——更新新版本的Gradle
问题: 你需要更新应用的Gradle版本. 解决方案: 生成一个新的wrapper,或者直接修改属性文件(.properties). 讨论: Android Studio包含了一个Gradle的分发. ...
- 【穿插】Python基础之文件、文件夹的创建,对上一期代码进行优化
在上一期妹子图的爬虫教程中,我们将图片都保存在了代码当前目录下,这样并不便于浏览,我们应该将同一个模特的图片都放在一个文件夹中. 今天我们就简单讲一下Python下如何创建文件.文件夹,今后就可以用上 ...
- 前台传递给后台的JSON字符串中的引号 “” 在JAVA后台被转义为 "
前台传递给后台的JSON字符串中的引号 "" 在JAVA后台被转义为 " 1.问题: 前台数据,JSON字符串带有引号 "" ,数据被传递到后台 ...
- Session基础知识
Session基础知识 主题 概念 Session的创建 Session的存储机制 Session的失效 参考资料 概念 Session代表一次用户会话.一次用户会话的含义是:从客 ...
- 检验指定路径的文件是否存在ftp服务器中
import org.apache.commons.net.ftp.FTP;import org.apache.commons.net.ftp.FTPClient;import org.apache. ...
- Xamarin.Forms学习之Page Navigation(二)
在上一篇的文章中,对页面常规的导航做一些分享,然而在实际的编程中,页面数据的保持,传值等等都有很多,这篇文章就对这些相关内容做一个分享和记录,有问题,希望大家留言指正.这一篇从实现业务逻辑来讲并没有什 ...
- text files and binary files
https://en.wikipedia.org/wiki/Text_file https://zh.wikipedia.org/wiki/文本文件
- FW 配置一个私有的Docker仓库
思维 66 3月1日 发布 建分支 0 分支 收藏 0 收藏 我们在本地开发时,如果内网能部署一台Docker服务器,无疑会极大的方便镜像的分享发布,有些私有镜像就是可以直接放到内网服务器上,省去了不 ...