侯体宗的博客
  • 首页
  • Hyperf版
  • beego仿版
  • 人生(杂谈)
  • 技术
  • 关于我
  • 更多分类
    • 文件下载
    • 文字修仙
    • 中国象棋ai
    • 群聊
    • 九宫格抽奖
    • 拼图
    • 消消乐
    • 相册

Python多线程原理与用法实例剖析

Python  /  管理员 发布于 7年前   151

本文实例讲述了Python多线程原理与用法。分享给大家供大家参考,具体如下:

先来看个栗子:

下面来看一下I/O秘籍型的线程,举个栗子――爬虫,下面是爬下来的图片用4个线程去写文件

#!/usr/bin/env python# -*- coding:utf-8 -*-import reimport urllibimport threadingimport Queueimport timeitdef getHtml(url):  html_page = urllib.urlopen(url).read()  return html_page# 提取网页中图片的URLdef getUrl(html):  pattern = r'src="https:/article/(http://img.*?)"' # 正则表达式  imgre = re.compile(pattern)  imglist = re.findall(imgre, html) # re.findall(pattern,string) 在string中寻找所有匹配成功的字符串,以列表形式返回值  return imglistclass getImg(threading.Thread):  def __init__(self, queue, thread_name=0): # 线程公用一个队列    threading.Thread.__init__(self)    self.queue = queue    self.thread_name = thread_name    self.start() # 启动线程  # 使用队列实现进程间通信  def run(self):    global count    while (True):      imgurl = self.queue.get() # 调用队列对象的get()方法从队头删除并返回一个项目      urllib.urlretrieve(imgurl, 'E:\mnt\girls\%s.jpg' % count)      count += 1      if self.queue.empty():        break      self.queue.task_done() # 当使用者线程调用 task_done() 以表示检索了该项目、并完成了所有的工作时,那么未完成的任务的总数就会减少。imglist = []def main():  global imglist  url = "http://huaban.com/favorite/beauty/" # 要爬的网页地址  html = getHtml(url)  imglist = getUrl(html)def main_1():  global count  threads = []  count = 0  queue = Queue.Queue()  # 将所有任务加入队列  for img in imglist:    queue.put(img)  # 多线程爬去图片  for i in range(4):    thread = getImg(queue, i)    threads.append(thread)  # 阻塞线程,直到线程执行完成  for thread in threads:    thread.join()if __name__ == '__main__':  main()  t = timeit.Timer(main_1)  print t.timeit(1)

4个线程的执行耗时为:0.421320716723秒

修改一下main_1换成单线程的:

def main_1():  global count  threads = []  count = 0  queue = Queue.Queue()  # 将所有任务加入队列  for img in imglist:    queue.put(img)  # 多线程爬去图片  for i in range(1):    thread = getImg(queue, i)    threads.append(thread)  # 阻塞线程,直到线程执行完成  for thread in threads:    thread.join()

单线程的执行耗时为:1.35626623274秒

再来看一个:

#!/usr/bin/env python# -*- coding:utf-8 -*-import threadingimport timeitdef countdown(n):  while n > 0:    n -= 1def task1():  COUNT = 100000000  thread1 = threading.Thread(target=countdown, args=(COUNT,))  thread1.start()  thread1.join()def task2():  COUNT = 100000000  thread1 = threading.Thread(target=countdown, args=(COUNT // 2,))  thread2 = threading.Thread(target=countdown, args=(COUNT // 2,))  thread1.start()  thread2.start()  thread1.join()  thread2.join()if __name__ == '__main__':  t1 = timeit.Timer(task1)  print "countdown in one thread ", t1.timeit(1)  t2 = timeit.Timer(task2)  print "countdown in two thread ", t2.timeit(1)

task1是单线程,task2是双线程,在我的4核的机器上的执行结果:

countdown in one thread  3.59939150155

countdown in two thread  9.87704289712

天呐,双线程比单线程计算慢了2倍多,这是为什么呢,因为countdown是CPU密集型任务(计算嘛)

I/O密集型任务:线程做I/O处理的时候会释放GIL,其他线程获得GIL,当该线程再做I/O操作时,又会释放GIL,如此往复;

CPU密集型任务:在多核多线程比单核多线程更差,原因是单核多线程,每次释放GIL,唤醒的哪个线程都能获取到GIL锁,所以能够无缝执行(单核多线程的本质就是顺序执行),但多核,CPU0释放GIL后,其他CPU上的线程都会进行竞争,但GIL可能会马上又被CPU0(CPU0上可能不止一个线程)拿到,导致其他几个CPU上被唤醒后的线程会醒着等待到切换时间后又进入待调度状态,这样会造成线程颠簸(thrashing),导致效率更低。

更多关于Python相关内容感兴趣的读者可查看本站专题:《Python进程与线程操作技巧总结》、《Python数据结构与算法教程》、《Python函数使用技巧总结》、《Python字符串操作技巧汇总》、《Python入门与进阶经典教程》、《Python+MySQL数据库程序设计入门教程》及《Python常见数据库操作技巧汇总》

希望本文所述对大家Python程序设计有所帮助。


  • 上一条:
    pycharm 将python文件打包为exe格式的方法
    下一条:
    对python读取CT医学图像的实例详解
  • 昵称:

    邮箱:

    0条评论 (评论内容有缓存机制,请悉知!)
    最新最热
    • 分类目录
    • 人生(杂谈)
    • 技术
    • linux
    • Java
    • php
    • 框架(架构)
    • 前端
    • ThinkPHP
    • 数据库
    • 微信(小程序)
    • Laravel
    • Redis
    • Docker
    • Go
    • swoole
    • Windows
    • Python
    • 苹果(mac/ios)
    • 相关文章
    • 在python语言中Flask框架的学习及简单功能示例(0个评论)
    • 在Python语言中实现GUI全屏倒计时代码示例(0个评论)
    • Python + zipfile库实现zip文件解压自动化脚本示例(0个评论)
    • python爬虫BeautifulSoup快速抓取网站图片(1个评论)
    • vscode 配置 python3开发环境的方法(0个评论)
    • 近期文章
    • 在go+gin中使用"github.com/skip2/go-qrcode"实现url转二维码功能(0个评论)
    • 在go语言中使用api.geonames.org接口实现根据国际邮政编码获取地址信息功能(1个评论)
    • 在go语言中使用github.com/signintech/gopdf实现生成pdf分页文件功能(0个评论)
    • gmail发邮件报错:534 5.7.9 Application-specific password required...解决方案(0个评论)
    • 欧盟关于强迫劳动的规定的官方举报渠道及官方举报网站(0个评论)
    • 在go语言中使用github.com/signintech/gopdf实现生成pdf文件功能(0个评论)
    • Laravel从Accel获得5700万美元A轮融资(0个评论)
    • 在go + gin中gorm实现指定搜索/区间搜索分页列表功能接口实例(0个评论)
    • 在go语言中实现IP/CIDR的ip和netmask互转及IP段形式互转及ip是否存在IP/CIDR(0个评论)
    • PHP 8.4 Alpha 1现已发布!(0个评论)
    • 近期评论
    • 122 在

      学历:一种延缓就业设计,生活需求下的权衡之选中评论 工作几年后,报名考研了,到现在还没认真学习备考,迷茫中。作为一名北漂互联网打工人..
    • 123 在

      Clash for Windows作者删库跑路了,github已404中评论 按理说只要你在国内,所有的流量进出都在监控范围内,不管你怎么隐藏也没用,想搞你分..
    • 原梓番博客 在

      在Laravel框架中使用模型Model分表最简单的方法中评论 好久好久都没看友情链接申请了,今天刚看,已经添加。..
    • 博主 在

      佛跳墙vpn软件不会用?上不了网?佛跳墙vpn常见问题以及解决办法中评论 @1111老铁这个不行了,可以看看近期评论的其他文章..
    • 1111 在

      佛跳墙vpn软件不会用?上不了网?佛跳墙vpn常见问题以及解决办法中评论 网站不能打开,博主百忙中能否发个APP下载链接,佛跳墙或极光..
    • 2016-10
    • 2016-11
    • 2018-04
    • 2020-03
    • 2020-04
    • 2020-05
    • 2020-06
    • 2022-01
    • 2023-07
    • 2023-10
    Top

    Copyright·© 2019 侯体宗版权所有· 粤ICP备20027696号 PHP交流群

    侯体宗的博客