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

作者:Andy冉明 时间:2023-07-22 13:40:37 

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

先来看个栗子:

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


#!/usr/bin/env python
# -*- coding:utf-8 -*-
import re
import urllib
import threading
import Queue
import timeit
def getHtml(url):
 html_page = urllib.urlopen(url).read()
 return html_page
# 提取网页中图片的URL
def getUrl(html):
 pattern = r'src="(http://img.*?)"' # 正则表达式
 imgre = re.compile(pattern)
 imglist = re.findall(imgre, html) # re.findall(pattern,string) 在string中寻找所有匹配成功的字符串,以列表形式返回值
 return imglist
class 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秒

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

再来看一个:


#!/usr/bin/env python
# -*- coding:utf-8 -*-
import threading
import timeit
def countdown(n):
 while n > 0:
   n -= 1
def 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密集型任务(计算嘛)

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

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

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

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

来源:https://www.cnblogs.com/onepiece-andy/p/python-thread-analyze.html

标签:Python,多线程
0
投稿

猜你喜欢

  • SQL Server 2000 作数据库服务器的优点

    2009-01-23 13:47:00
  • pandas分组聚合详解

    2023-06-28 15:50:25
  • Thinkphp5文件包含漏洞解析

    2023-07-01 19:42:51
  • Photoshop设计制作网站流程图解

    2007-10-25 12:06:00
  • “您无权查看该网页”的原因和解决方法

    2008-03-24 16:57:00
  • Sql Server、Oracle以及Access数据库 判断字段是否为空的办法 (From calmzeal's code life)

    2011-02-24 19:44:00
  • 仿淘宝网站的导航标签效果!

    2008-11-05 12:37:00
  • 如何用SQLMail建立一个电子刊物自动处理系统?

    2010-06-13 14:36:00
  • SQL Server 自动增长清零的方法

    2012-01-05 19:07:47
  • Go语言中的Array、Slice、Map和Set使用详解

    2023-06-24 07:29:03
  • 页面制作的重要性

    2007-10-30 13:14:00
  • js倒记时代码,自定义时间改变时间,日期到时事件,日期格式。

    2010-08-08 08:51:00
  • 数据库安全管理的三个经验分享

    2009-04-01 15:49:00
  • 如何选择合适的MySQL存储引擎

    2009-02-04 13:02:00
  • SQL server使用自定义函数以及游标

    2011-11-03 17:26:27
  • 两个百度WEB面试题 怎么做?

    2010-09-03 18:40:00
  • ASP用JAVASCRIPT脚本实现分页的办法

    2007-10-30 13:18:00
  • 能否用显示/隐藏层来控制FLASH播放与停止

    2008-10-27 14:08:00
  • 网页用多宽才更合适?

    2009-04-07 14:07:00
  • sql exist的妙用

    2007-11-08 11:47:00
  • asp之家 网络编程 m.aspxhome.com