Python多线程原理与用法实例剖析
作者:Andy冉明 发布时间:2023-07-22 13:40:37
标签:Python,多线程
本文实例讲述了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秒
再来看一个:
#!/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密集型任务(计算嘛)
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


猜你喜欢
- 1.获取当前时间的两种方法:import datetime,timenow = time.strftime("%Y-%m-%d %
- 1.不装入数据库而启动事例 可以不装入数据库而启动事例,一般是在数据库才创建时才可以这样做:STARTUP NOMOUNT2.启动事例并装入
- 如下所示:class Login(QMainWindow): """登录窗口""
- 本文实例为大家分享了JavaScript实现简易轮播图效果的具体代码,供大家参考,具体内容如下全部代码:<!DOCTYPE html&
- 前言minio分享文件的链接,最多支持分享七天通过 MinIO客户端 管理存储桶策略的方式实现文件链接永久有效1.下载MinIO Clien
- 点工具栏中〔显示估计的查询计划〕,结果提示Documents and Settings\XXX\Local Settings\Temp\1\
- 上一篇我们讲过Cookie相关的知识,了解到Cookie是为了交互式web而诞生的,它主要用于以下三个方面:会话状态管理(如用户登录状态、购
- 本文主要讲述:自定义树形控件<el-tree>需求说明:Element UI 官网提供的树形控件包含基础的、可选择的、自定义节点
- 今天我将教大家如何用哈希函数将密码加密加密后的密码是很难倒推的~普通加密:首先调用函数hashlibimport hashlib然后使用哈希
- 1,效果图 2,实现方法const columns = [ { title: '序号',  
- 之前使用email模块+smtplib模块发送邮件,虽然可以实现功能,但过程比较繁琐,今天发现一个宝藏库(yagmail),可以说是炒鸡好用
- ActiveMQ是java开发的消息中间件服务。可以支持多种协议(AMQP,MQTT,OpenWire,Stomp),默认的是OpenWir
- 一. 介绍fire是python中用于生成命令行界面(Command Line Interfaces, CLIs)的工具,不需要做任何额外的
- javascript上下滑动广告效果 参数说明:客服果果(
- 前言:用xtarbackup来同步数据,然后基于GTID来设置主从。一、用xtarbackup备份数据库1.1 优势使用xtarbackup
- 依赖安装Python安装git安装Django1.去Python官网下载Python3.6并配置好环境变量 Python下载地址:https
- 本文实例讲述了python使用协程实现并发操作的方法。分享给大家供大家参考,具体如下:协程协程是一种用户态的轻量级线程,又称微线程。协程拥有
- 1._thread.start_new_thread(了解)import threadingimport timeimport _threa
- 带你了解CGO编程大学时最开始学的语言莫过于C/C++,C/C++经过几十年的发展,已经积累了庞大的软件资产,它们很多久经考验而且性能已经足
- 人工生命—群集智能—蚁群算法js版前言(摘自网上,代码是自己想出来的)对于普通大众来说,“人工生命”、“群集智能”、“仿生机器人”等等可能是