python多线程与多进程
多线程与多进程
一, 什么是进程, 什么是线程?
进程: 运行中的程序. 每次我们执行一个程序, 咱们的操作系统对自动的为这个程序准备一些必要的资源(例如, 分配内存, 创建一个能够执行的线程. )
线程: 程序内, 可以直接被CPU调度的执行过程. 是操作系统能够进行运算调度的最小单位. 它被包含在进程之中, 是进程中的实际运作单位.
进程与线程之间的关系:
进程是资源单位. 线程是执行单位. 就好比是一家公司. 一家公司的资源就是桌椅板凳, 电脑饮水机这些资源, 但是, 我们如果说一家公司正在运转着, 运行着. 那里面必须要有能为这家公司工作的人. 程序里面也一样, 进程就是为了程序运行而需要的各种资源. 但是程序想要运行, 就必须由线程来被CPU调度执行.
我们运行的每一个程序默认都会有一个线程. 哪怕是只有helloworld级别的程序. 想要执行. 也会有一个线程产生.
二, 多线程
顾名思义, 多线程就是让程序产生多个线程一起去执行. 还拿公司举例子. 一家公司里如果只有一个员工, 工作效率肯定不会高到哪里去. 怎么提高效率? 多招点儿人就OK了.
如何实现多线程, 在python中, 有两种方案实现多线程.
1. 直接用Thread创建线程
我们先看看单线程的效果
def func():for i in range(1000):print("func", i)if __name__ == '__main__':func()for i in range(1000):print("main", i)
再看多线程
from threading import Threaddef func():for i in range(1000):print("func", i)if __name__ == '__main__':t = Thread(target=func)t.start()for i in range(1000):print("main", i)
2. 继承Thread类
from threading import Threadclass MyThread(Thread):def run(self):for i in range(1000):print("func", i)if __name__ == '__main__':t = MyThread()t.start()for i in range(1000):print("main", i)
以上两种是最基本的python创建多线程的方案. python还提供了线程池
3. 线程池
python还提供了线程池功能. 可以一次性的创建多个线程, 并且, 不需要我们程序员手动去维护. 一切都交给线程池来自动管理.
# 线程池
def fn(name):for i in range(1000):print(name, i)if __name__ == '__main__':with ThreadPoolExecutor(10) as t:for i in range(100):t.submit(fn, name=f"线程{i}")
如果任务有返回值怎么办?
def func(name):time.sleep(2)return namedef do_callback(res):print(res.result())if __name__ == '__main__':with ThreadPoolExecutor(10) as t:names = ["线程1", "线程2", "线程3"]for name in names:# 方案一, 添加回调t.submit(func, name).add_done_callback(do_callback)if __name__ == '__main__':start = time.time()with ThreadPoolExecutor(10) as t:names = [5, 2, 3]# 方案二, 直接用map进行任务分发. 最后统一返回结果results = t.map(func, names, ) # 结果是按照你传递的顺序来执行的, 代价就是如果第一个没结束. 后面就都没结果for r in results:print("result", r)print(time.time() - start)
4. 多线程在爬虫中的应用
http://www.xinfadi.com.cn/marketanalysis/0/list/1.shtml
依然用新发地这个案例.
import requests
from lxml import etree
from concurrent.futures import ThreadPoolExecutordef get_page_source(url):resp = requests.get(url)return resp.textdef get_totle_count():url = "http://www.xinfadi.com.cn/marketanalysis/0/list/1.shtml"source = get_page_source(url)tree = etree.HTML(source)last_href = tree.xpath("//div[@class='manu']/a[last()]/@href")[0]totle = last_href.split("/")[-1].split(".")[0]return int(totle)def download_content(url):source = get_page_source(url)tree = etree.HTML(source)trs = tree.xpath("//table[@class='hq_table']/tr[position() > 1]")result = []for tr in trs:tds = tr.xpath("./td/text()")result.append((tds[0], tds[1], tds[2], tds[3], tds[4], tds[5], tds[6]))return resultdef main():f = open("data.csv", mode="w")totle = get_totle_count()url_tpl = "http://www.xinfadi.com.cn/marketanalysis/0/list/{}.shtml"with ThreadPoolExecutor(50) as t:data = t.map(download_content, (url_tpl.format(i) for i in range(1, totle+1)))# 拿到所有任务的返回for item in data:# 每个任务的数据循环出一行for detial in item:# 写入文件content = ",".join(detial) + "\n"print(content)f.write(content)if __name__ == '__main__':main()
三, 多进程
一个公司能创造的价值毕竟是有限的. 怎么办? 开分公司啊. 此所谓多进程. python实现多进程的方案和多线程几乎一样. 非常的简单
###1. 直接用Process创建进程
def func():for i in range(1000):print("func", i)if __name__ == '__main__':p = Process(target=func)p.start()for i in range(1000):print("main", i)
2. 继承Process类
class MyProcess(Process):def run(self):for i in range(1000):print("MyProcess", i)if __name__ == '__main__':t = MyProcess()t.start()for i in range(1000):print("main", i)
###3.多进程在爬虫中的应用
我们一般很少直接使用多进程. 最适合使用多进程的情况是: 多个任务需要一起执行. 并且互相之间数据可能有交汇但功能相对独立.比如, 我们自己做一个代理IP池, 就需要从网络上进行抓取, 抓取得到的IP要进行校验才可以进行使用. 此时, 抓取任务和校验任务就相当于完全独立的两个功能. 此时就可以启动多个进程来实现. 再比如, 如果遇到图片抓取的时候, 我们知道图片在一般都在网页的img标签中src属性存放的是图片的下载地址. 此时我们可以采用多进程的方案来实现, 一个负责疯狂扫图片下载地址. 另一个进程只负责下载图片.
综上, 多个任务需要并行执行, 但是任务之间相对独立(不一定完全独立). 可以考虑用多进程.
# 进程1. 从图片网站中提取到图片的下载路径
def get_pic_src(q):print("start main page spider")url = "http://www.591mm.com/mntt/"resp = requests.get(url)tree = etree.HTML(resp.text)child_hrefs = tree.xpath("//div[@class='MeinvTuPianBox']/ul/li/a/@href")print("get hrefs from main page", child_hrefs)for href in child_hrefs:href = parse.urljoin(url, href)print("handle href", href)resp_child = requests.get(href)tree = etree.HTML(resp_child.text)pic_src = tree.xpath("//div[@id='picBody']//img/@src")[0]print(f"put {pic_src} to the queue")q.put(pic_src)# 作业, 分页图片抓取# print("ready to another!")# others = tree.xpath('//ul[@class="articleV2Page"]')# if others:# 进程2. 从图片网站中提取到图片的下载路径
def download(url):print("start download", url)name = url.split("/")[-1]resp = requests.get(url)with open(name, mode="wb") as f:f.write(resp.content)resp.close()print("downloaded", url)def start_download(q):with ThreadPoolExecutor(20) as t:while True:t.submit(download, q.get()) # 启动def main():q = Queue()p1 = Process(target=start_download, args=(q,))p2 = Process(target=get_pic_src, args=(q,))p1.start()p2.start()if __name__ == '__main__':main()相关文章:
python多线程与多进程
多线程与多进程 一, 什么是进程, 什么是线程? 进程: 运行中的程序. 每次我们执行一个程序, 咱们的操作系统对自动的为这个程序准备一些必要的资源(例如, 分配内存, 创建一个能够执行的线程. ) 线程: 程序内, 可以直接被CPU调度的执行过程. 是操作系统能够进行运算调度…...
62从零开始学Java之时间相关的类都有哪些?
作者:孙玉昌,昵称【一一哥】,另外【壹壹哥】也是我哦 千锋教育高级教研员、CSDN博客专家、万粉博主、阿里云专家博主、掘金优质作者 前言 我们在开发时,除了数字、数学这样的常用API之外,还有日期时间类,更…...
【Leetcode】买卖股票系列
121. 买卖股票的最佳时机 给定一个数组 prices ,它的第 i 个元素 prices[i] 表示一支给定股票第 i 天的价格。 你只能选择 某一天 买入这只股票,并选择在 未来的某一个不同的日子 卖出该股票。设计一个算法来计算你所能获取的最大利润。 返回你可以从这笔…...
SLAM面试笔记(8) — 计算机视觉面试题
目录 问题1:目标检测的算法分类 问题2:卷积神经网络的组成 问题3:输入层的作用 问题4:卷积层作用 问题5:卷积核类型 问题6:11卷积核作用 问题7:卷积核是否越大越好 问题8:棋…...
聊聊MySQL面试常问名词回表、索引覆盖,最左匹配
文章目录 1. 前言2. 回表操作 Index Lookup2.1 什么是回表2.2 回表的成本2.3 如何避免回表 3. 索引覆盖 Covering Index3.1 什么是索引覆盖3.2 索引覆盖的优点3.3 如何使用索引覆盖 4. 最左匹配原则(Leftmost Prefix Match)4.1 什么是最左匹配原则4.2 最…...
【面试】C/C++面试八股
C/C面试八股 编译过程的四个阶段C和C语言的区别简单介绍一下三大特性多态的实现原理虚函数的构成原理虚函数的调用原理虚表指针在什么地方进行初始化的?构造函数为什么不能是虚函数为什么建议将析构函数设为虚函数虚函数和纯虚函数的区别抽象类类对象的对象模型内存…...
学习记忆——数学篇——算术——无理数
谐音记忆法 2 \sqrt{2} 2 ≈1.41421:意思意思而已;意思意思; 3 \sqrt{3} 3 ≈1.7320:—起生鹅蛋;一起生儿; 5 \sqrt{5} 5 ≈2.2360679:两鹅生六蛋(送)六妻舅;儿儿生…...
python协程和任务
协程概念引入 协程是我要重点去讲解的一个知识点. 它能够更加高效的利用CPU. 其实, 我们能够高效的利用多线程来完成爬虫其实已经很6了. 但是, 从某种角度讲, 线程的执行效率真的就无敌了么? 我们真的充分的利用CPU资源了么? 非也~ 比如, 我们来看下面这个例子. 我们…...
visual studio code配置anaconda3的python虚拟环境
参考: Visual Studio Code配置anconda3虚拟环境 - 知乎...
【Unity3D编辑器开发】Unity3D编辑器开发基础性框架结构【全面总结】
推荐阅读 CSDN主页GitHub开源地址Unity3D插件分享简书地址我的个人博客 大家好,我是佛系工程师☆恬静的小魔龙☆,不定时更新Unity开发技巧,觉得有用记得一键三连哦。 一、前言 嗨,大家好,我是恬静的小魔龙。 同学们…...
一座“城池”:泡泡玛特主题乐园背后,IP梦想照亮现实
“更适合中国宝宝体质”的主题乐园,被泡泡玛特造出来了。 9月26日,位于北京朝阳公园内的国内首个潮玩行业沉浸式 IP 主题乐园,也是泡泡玛特首个线下乐园——泡泡玛特城市乐园 POP LAND正式开园。 约4万平方米的空间中,泡泡玛特使…...
【什么是闭包? 闭包产生的原因? 闭包有哪些表现形式?】
JS闭包 什么是闭包?闭包产生的原因?闭包有哪些表现形式? 什么是闭包? 闭包是指一个函数可以访问并操作在其作用域之外的变量的能力。在 JavaScript 中,每当函数被创建时,就会创建一个闭包。 以下是一个简单的闭包示例…...
JackJson和FastJson
前言: fastjson是一款强大的json格式转换工具,我个人在开发中就非常喜欢用fastjson;但是由于某些原因,导致fastjson会有一些漏洞,因此在漏洞扫描后需要修复都是要求我们升级版本,或者替换为jackjson&#…...
SpringCloud学习一
单体应用存在的问题 随着业务的发展,开发变得越来越复杂。 修改、新增某个功能,需要对整个系统进行测试、重新部署。 一个模块出现问题,很可能导致整个系统崩溃。 多个开发团队同时对数据进行管理,容易产生安全漏洞。 各个模块…...
SpringBoot, EventListener事件监听的使用
1、背景 在开发工作中,会遇到一种场景,做完某一件事情以后,需要广播一些消息或者通知,告诉其他的模块进行一些事件处理,一般来说,可以一个一个发送请求去通知,但是有一种更好的方式,…...
课题学习(三)----倾角和方位角的动态测量方法(基于陀螺仪的测量系统)
一、内容介绍 该测量系统基于三轴加速度和三轴陀螺仪,安装在钻柱内部,随钻柱一起旋转,形成捷联惯性导航系统,安装如下图所示: 假设三轴加速度和陀螺仪的输出为: f b [ f x f y f z ] T f^b\begin{bmatrix}f_{x} …...
1876. 长度为三且各字符不同的子字符串
1876. 长度为三且各字符不同的子字符串 C代码:滑动窗口 // 存在三种字符,且不重复、子串数量 int countGoodSubstrings(char * s){int k 3;int hash[26] {0};int len 0;int l 0;int ans 0;for (int i 0; i < strlen(s); i) {hash[s[i] - a];if…...
Mall脚手架总结(一)——SpringSecurity实现鉴权认证
前言 在结束理论知识的学习后,荔枝开始项目学习,这个系列文章将围绕荔枝学习mall项目过程中总结的知识点来梳理。本篇文章主要涉及如何整合Spring Security和JWT实现鉴权认证的功能!希望能帮助到一起学习mall项目的小伙伴~~~ 文章目录 前言 …...
beego-简单项目写法--路径已经放进去了
Beego案例-新闻发布系统 1.注册 后台代码和昨天案例代码一致。,所以这里面只写一个注册的业务流程图。 **业务流程图 ** 2.登陆 业务流程图 登陆和注册业务和我们昨天登陆和注册基本一样,所以就不再重复写这个代码 但是我们遇到的问题是如何做代码的迁移&…...
Spark 之 入门讲解详细版(1)
1、简介 1.1 Spark简介 Spark是加州大学伯克利分校AMP实验室(Algorithms, Machines, and People Lab)开发通用内存并行计算框架。Spark在2013年6月进入Apache成为孵化项目,8个月后成为Apache顶级项目,速度之快足见过人之处&…...
DeepSeek 赋能智慧能源:微电网优化调度的智能革新路径
目录 一、智慧能源微电网优化调度概述1.1 智慧能源微电网概念1.2 优化调度的重要性1.3 目前面临的挑战 二、DeepSeek 技术探秘2.1 DeepSeek 技术原理2.2 DeepSeek 独特优势2.3 DeepSeek 在 AI 领域地位 三、DeepSeek 在微电网优化调度中的应用剖析3.1 数据处理与分析3.2 预测与…...
【JavaEE】-- HTTP
1. HTTP是什么? HTTP(全称为"超文本传输协议")是一种应用非常广泛的应用层协议,HTTP是基于TCP协议的一种应用层协议。 应用层协议:是计算机网络协议栈中最高层的协议,它定义了运行在不同主机上…...
从WWDC看苹果产品发展的规律
WWDC 是苹果公司一年一度面向全球开发者的盛会,其主题演讲展现了苹果在产品设计、技术路线、用户体验和生态系统构建上的核心理念与演进脉络。我们借助 ChatGPT Deep Research 工具,对过去十年 WWDC 主题演讲内容进行了系统化分析,形成了这份…...
day52 ResNet18 CBAM
在深度学习的旅程中,我们不断探索如何提升模型的性能。今天,我将分享我在 ResNet18 模型中插入 CBAM(Convolutional Block Attention Module)模块,并采用分阶段微调策略的实践过程。通过这个过程,我不仅提升…...
Vue2 第一节_Vue2上手_插值表达式{{}}_访问数据和修改数据_Vue开发者工具
文章目录 1.Vue2上手-如何创建一个Vue实例,进行初始化渲染2. 插值表达式{{}}3. 访问数据和修改数据4. vue响应式5. Vue开发者工具--方便调试 1.Vue2上手-如何创建一个Vue实例,进行初始化渲染 准备容器引包创建Vue实例 new Vue()指定配置项 ->渲染数据 准备一个容器,例如: …...
CocosCreator 之 JavaScript/TypeScript和Java的相互交互
引擎版本: 3.8.1 语言: JavaScript/TypeScript、C、Java 环境:Window 参考:Java原生反射机制 您好,我是鹤九日! 回顾 在上篇文章中:CocosCreator Android项目接入UnityAds 广告SDK。 我们简单讲…...
ElasticSearch搜索引擎之倒排索引及其底层算法
文章目录 一、搜索引擎1、什么是搜索引擎?2、搜索引擎的分类3、常用的搜索引擎4、搜索引擎的特点二、倒排索引1、简介2、为什么倒排索引不用B+树1.创建时间长,文件大。2.其次,树深,IO次数可怕。3.索引可能会失效。4.精准度差。三. 倒排索引四、算法1、Term Index的算法2、 …...
【C语言练习】080. 使用C语言实现简单的数据库操作
080. 使用C语言实现简单的数据库操作 080. 使用C语言实现简单的数据库操作使用原生APIODBC接口第三方库ORM框架文件模拟1. 安装SQLite2. 示例代码:使用SQLite创建数据库、表和插入数据3. 编译和运行4. 示例运行输出:5. 注意事项6. 总结080. 使用C语言实现简单的数据库操作 在…...
RNN避坑指南:从数学推导到LSTM/GRU工业级部署实战流程
本文较长,建议点赞收藏,以免遗失。更多AI大模型应用开发学习视频及资料,尽在聚客AI学院。 本文全面剖析RNN核心原理,深入讲解梯度消失/爆炸问题,并通过LSTM/GRU结构实现解决方案,提供时间序列预测和文本生成…...
