学习日志012--python中多进程,多线程

简简单单小练习

1.线程的并发执行

import threading
import time# 创建要执行的两个函数
def print_hello():for _ in range(10):print("hello")time.sleep(1)def print_world():for _ in range(10):print("world")time.sleep(1)# 创建线程对象 注意这里要写函数名,不能调用函数
thread_hello = threading.Thread(target=print_hello)
thread_world = threading.Thread(target=print_world)# 开始进行线程
thread_hello.start()
thread_world.start()# 等待线程结束
thread_hello.join()
thread_world.join()

总结:

  1. 准备一个函数。
  2. 使用 import threading 创建一个线程对象 t 。
  3. 使用 t.start() 来启动线程。
  4. 使用 t.join() 来等待线程的结束.

2.单线程与多线程的比较

下面是一个简单的爬虫案例,我们之后将用单线程与多线程分别操作进行比较

import requestsurls = [f"https://www.cnblogs.com/#p{page}" for page in range(1,51)]def craw(url):r = requests.get(url)print(url,len(r.text))craw(urls[0])
import threading
import time
import requestsurls = [f"https://www.cnblogs.com/#p{page}" for page in range(1,51)]def craw(url):r = requests.get(url)print(url,len(r.text))# 这里由于列表在函数上面作为全局变量,故没使用参数
def single_thread():print("单线程函数开始")# 遍历每一个网页for url in urls:craw(url)print("single_thread end")def multi_thread():"""多进程函数这里是真正的多线程操作之前的是通过休眠来模拟:return:"""print("multi_thread begin")# 创建空列表接受线程threads = []# 将创建的多个线程对象存入列表中for url in urls:threads.append(threading.Thread(target=craw,args=(url,)))# 启动线程for thread in threads:thread.start()# 等待线程结束for thread in  threads:thread.join()print("multi_thread end")# 确定作为主程序执行
if __name__ == '__main__':# 建立时间标记start = time.time()single_thread()end = time.time()print(f"单线程需要{end - start}秒")start = time.time()multi_thread()end = time.time()print(f"多线程需要{end - start}秒")
multi_thread begin
单线程需要6.053725004196167秒
single_thread endmulti_thread begin多线程需要0.2576422691345215秒
multi_thread end

从结果来看多线程的确能缩短进程所需时间,但面对大数据这些还是不够看,这时就要请出消费者生产者模型,简单来说就是边查边处理数据

import threading
import time
import requests
from bs4 import BeautifulSoup# 创建网址列表urls = [(f"https://www.cnblogs.com/#p{page}") for page in range(1,51)]# 生产者获取网址元素
def craw(url):r = requests.get(url)return r.text# 消费者将获取到的元素计算
def parse(html):# html时指定的对象 html.parser是指定的解析器soup = BeautifulSoup(html,"html.parser")#这里使用BS的方法根据关键字类查找信息links = soup.find_all("a",class_ = "post-item-title")# 返回解析的列表return [(link["href"],link.get_text()) for link in links]if __name__ == '__main__':for result in parse(craw(urls[2])):print(result)

 这里我们利用之前学的模块在新的python文件内实现

import threading
import time
import requests
from bs4 import BeautifulSoup# 创建网址列表urls = [(f"https://www.cnblogs.com/#p{page}") for page in range(1,51)]# 生产者获取网址元素
def craw(url):r = requests.get(url)return r.text# 消费者将获取到的元素计算
def parse(html):# html时指定的对象 html.parser是指定的解析器soup = BeautifulSoup(html,"html.parser")#这里使用BS的方法根据关键字类查找信息links = soup.find_all("a",class_ = "post-item-title")# 返回解析的列表return [(link["href"],link.get_text()) for link in links]if __name__ == '__main__':for result in parse(craw(urls[2])):print(result)
import randomfrom jinja2.utils import url_quoteimport part_1
import threading
import time
import requests
from bs4 import BeautifulSoup
import queue# 创建两个队列一个负责接受网页,一个负责接受网页解析下的元素
def do_craw(url_queue:queue.Queue,html_queue:queue.Queue):while True:# 队列的get方法,即出队,指向队首url = url_queue.get()# 捕获网页html = part_1.craw(url)# 队列的put方法即入列html_queue.put(html)# 打印相关日志print(threading.current_thread().name,f"craw{url}","url_queue.size = ",url_queue.qsize())time.sleep(random.randint(1,2))def do_parse(html_queue:queue.Queue,fout):while True:# 出队html = html_queue.get()# 队列的put方法即入列results = part_1.parse(html)for result in results:fout.write(str(result)+"\n")# 打印相关日志print(threading.current_thread().name,f"results.size",len(results),"html_queue_size=",html_queue.qsize())time.sleep(random.randint(1,2))if __name__ == '__main__':url_queue  = queue.Queue()html_queue = queue.Queue()for url in part_1.urls:url_queue.put((url))for idx in range(3):t = threading.Thread(target=do_craw,args=(url_queue,html_queue),name=f"craw{idx}")t.start()fout = open("spider_data.txt","w")for idx in range(2):t = threading.Thread(target=do_parse,args=(html_queue,fout),name=f"parse{idx}")t.start()

 

笔记

不知你还记不记得这样一个问题,小华煮饭花费20分钟,炒菜5分钟,洗菜5分钟,淘米5分钟,打扫卫生10分钟,问一共花费多长时间?通过这道题了解到,有时候我们可以’同时‘做多件事情。计算机也能将任务分解成多个小问题,花费更少的时间资源。

譬如

场景1:一个网络爬虫,顺序爬取一个网页花了一个小时,采用并发下载就减少到了20分钟。

场景2:一个应用软件优化前每次打开网页需要3秒,采用异步并发提升到了200毫秒。

假设一个工程的工作量为100,不采用并发编程就相当于由一个人去完成这个工作量为100的所有工作内容,可能需要1个小时来做完。

但是还是这工作量为100的工程,我们采用并发编程就相当于是由2个人或者3个人去共同完成这份100工作量的工作,可能这份工作只需要半个小时就能做完。

总之引入并发就相当于提升程序进行速度

进程、线程

概念

程序:程序是一系列按照特定顺序组织的计算机指令和数据的集合,这些指令和数据被设计用来执行特定的任务或解决特定的问题。程序是静态的,它存在于磁盘等存储介质上,等待被加载和执行。程序本身不占用系统的运行资源,如CPU、内存等

与进程和线程的关系‌:程序是进程和线程的基础,一个程序可以被多次加载和执行,形成多个进程或线程。我们下载好的软件是程序,当我们运行他时,创建了进程。 

进程:进程是具有一定独立功能的程序在某个数据集合上的一次执行过程,是操作系统进行资源分配和保护的基本单位。进程赋予程序以生命活力,让静态的程序,变得动态起来。进程具有动态性,它拥有自己的地址空间、全局变量、文件句柄等资源,可以独立地执行程序中的指令。进程是系统资源分配和调度的基本单位,每个进程都有自己的生命周期,可以因创建而产生,因完成任务而被撤消。

与线程和程序的关系‌:进程是程序的一次执行过程,一个程序可以对应多个进程。同时,进程内部可以包含多个线程,这些线程共享进程的资源

线程:线程是进程中的一个执行单元,是操作系统能够进行运算调度的最小单位。线程共享进程的资源,如地址空间、全局变量等,但具有自己独立的栈、程序计数器以及局部变量等。线程可以并发执行,提高程序的执行效率。线程的切换比进程的切换更加快速和高效。

与进程和程序的关系‌:线程是进程中的一个执行路径,一个进程可以包含多个线程。线程是程序并发执行的基础,通过合理地使用线程,可以提高程序的响应速度、执行效率和资源利用率。

 从终端输入tasklist后我们可以看到当前的进程

程序提速的方法(从进程与线程角度上说)

1.我们之前练习的代码多是按照顺序执行,即单线程执行的,比如一个线程执行开始后开始CPU【运算器和控制器】执行,之后进行IO操作,在IO完成之后CPU再次进行运算,也就是说在这个线程的执行过程中CPU与IO是不能同时工作的。

缺点:在整体时间上有些浪费,在CPU工作时,IO并不工作,如果他们能共同工作就好了。

2.多线程执行。从之前的导言里我们知道一段代码的执行是由最基本的单元线程来计算的。可不可以分配好任务让多个线程同时运行呢?答案是肯定的。

此时情况为在CPU工作时,IO同样能进行。CPU进行工作,当运行到IO操作后,此时就会有一个新的task去执行IO操作,CPU也可以继续执行自己的运算,当IO完成后也会通知CPU进行下一步的处理。就像电饭煲专门负责做饭,需要大量蒸饭时,煤气灶不影响微波炉运转,同时也能蒸饭。

注意:CPU运算与IO操作,这两个是可以同时并行执行的,也就是说在IO读取内存磁盘的时候,这个过程是不需要CPU参与的,CPU与IO可以同时处理自己工作,这相对于单线程串行来说就实现了并行的加速效果,更加合理的利用了时间资源。

3.多cpu执行。多这种多核CPU多条线同时处理我们的程序,这种并行的方式才是真正的并发。就像多个厨师,可运用多个灶台,主要解决需要大量计算操作的问题。

Python对并发编程的支持

  1. 多线程:threading模块,利用CPU和IO可以同时执行的原理,让CPU不会干巴巴的等待IO完成。
  2. 多进程:multiprocessing模块,利用多核CPU的能力,真正的并行执行任务。
  3. 异步IO:asyncio模块,在单线程中利用CPU和IO同时执行的原理,实现函数异步执行。

Python还提供了辅助这些模块的函数:

  1. 多线程与多进程同时访问同一个文件同时写入的话就会冲突,可以使用Python提供的Lock来对资源进行加锁,防止冲突访问,就能实现顺序访问同一个文件。
  2. 使用Queue模块(队列)实现不同线程/进程之间的数据通信,实现生产者-消费者模式,比如实现一个生产者消费者模式来改造爬虫,生产者一边爬取,消费者就一边解析。
  3. 使用线程池/进程池,简化线程/进程的任务提交,等待结束,获取结果。
  4. 使用subprocess启动外部程序的进程,并进行输入输出交互。

Python怎样选择多线程,多进程与多协程

 什么是CPU密集型计算,IO密集型计算

CPU密集型其实就是你程序的运行最终会受到CPU的限制,CPU是你程序运行的瓶颈,IO密集型则是你程序的运行最终会受到IO的限制,IO是你程序运行的瓶颈。

CPU密集型(CPU-bound):

CPU密集型也叫计算密集型,是指IO操作在很短的时间内就能完成,CPU需要大量的计算和处理,而并不需要频繁的磁盘读写,网络传输等操作,特点是CPU占用率相当高。

例如:加密解密,图像处理,科学计算等需要大量的CPU运算能力以及较少的IO操作等任务。

并行优势:【多进程】CPU密集型任务可以通过并行在不同的处理器核心上同时执行提高性能。

IO密集型(IO-bound):

IO密集型指的是系统运作大部分的状况是CPU在等IO(硬盘/内存)的读/写操作,CPU占用率低,不需要CPU进行大量的运算,CPU大部分时间通常是在等待IO操作的完成。

例如:文件处理程序,读写程序库程序,网络爬虫程序,用户输入等需要大量的IO操作而较少的CPU运算等任务。

并发优势:【多线程】IO密集型任务可以通过并发执行来提高效率,因为在等待一个IO操作完成时,CPU可以切换到另一个任务执行。

多线程,多进程与多协程的对比

多进程 Process(multiprocessing)

优点:可以利用多核CPU并行运算

缺点:占用资源最多,可启动数目比线程少,受CPU的限制

适用:CPU密集型计算,你比如自己使用IO读取了数据,然后需要在CPU上运行大量的次数和时间这个时候就可以使用进程process来实现

多线程 Thread(threading)

一个进程中可以启动N个线程

优点:相比进程,更加轻量级,占用资源少

缺点:相比进程:Python多线程只能并发执行,也就是说只能同时使用一个CPU,不能利用多CPU(因为一个叫GIL的东西)

相比协程:启动数目有限制,占用内存资源,有线程切换开销

适用:IO密集型计算,并且同时运行的任务数目要求不多

多协程 Coroutine(asyncio)

在单线程内通过协作方式切换执行任务,实现函数异步执行。

优点:内存开销最小,启动协程数量最多

缺点:支持的库有限制,代码实现复杂

怎样根据任务选择对应技术

拿到我们的任务后,首先分析我们的任务特点:

  1. 如果任务需要大量的CPU运算,那他就属于我们的CPU密集型,此时我们采用多进程multiprocessing来实现。
  2. 如果任务需要大量的IO操作,那他就属于我们的IO密集型了,此时我们应该采用多线程threading来实现或者多协程asyncio来实现。

对于多线程与多协程我们应该如何选择呢,一般如果我们符合以下三点,我们就会使用多协程来实现,否则就会采用多线程来实现

这三点分别是:

  1. 是否有超多任务量
  2. 是否有线程的协程库来支持
  3. 协程实现的复杂度是不是能够接受

如果这三点都能够满足,那么我们不妨尝试使用协程来实现我们的任务,因为我们的协程是一个新的技术,性能会最好。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/474274.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

网络传输:网卡、IP、网关、子网掩码、MAC、ARP、路由器、NAT、交换机

目录 网卡IP网络地址主机地址子网子网掩码网关默认网关 MACARPARP抓包分析 路由器NATNAPT 交换机 网卡 网卡(Network Interface Card,简称NIC),也称网络适配器。 OSI模型: 1、网卡工作在OSI模型的最后两层,物理层和数据链路层。物…

Ubuntu 22.04 上快速搭建 Samba 文件共享服务器

Samba 简介 Samba 是一个开源软件,它扮演着不同操作系统间沟通的桥梁。通过实现 SMB(Server Message Block)协议,Samba 让文件和打印服务在 Windows、Linux 和 macOS 之间自由流动。 以下是 Samba 的特点: 跨平台兼…

stm32启动过程解析startup启动文件

1.STM32的启动过程模式 1.1 根据boot引脚决定三种启动模式 复位后,在 SYSCLK 的第四个上升沿锁存 BOOT 引脚的值。BOOT0 为专用引脚,而 BOOT1 则与 GPIO 引脚共用。一旦完成对 BOOT1 的采样,相应 GPIO 引脚即进入空闲状态,可用于…

CVE-2024-2961漏洞的简单学习

简单介绍 PHP利用glibc iconv()中的一个缓冲区溢出漏洞,实现将文件读取提升为任意命令执行漏洞 在php读取文件的时候可以使用 php://filter伪协议利用 iconv 函数, 从而可以利用该漏洞进行 RCE 漏洞的利用场景 PHP的所有标准文件读取操作都受到了影响&#xff1…

视觉SLAM相机——单目相机、双目相机、深度相机

一、单目相机 只使用一个摄像头进行SLAM的做法称为单目SLAM,这种传感器的结构特别简单,成本特别低,单目相机的数据:照片。照片本质上是拍摄某个场景在相机的成像平面上留下的一个投影。它以二维的形式记录了三维的世界。这个过程中…

Java通过calcite实时读取kafka中的数据

引入maven依赖 <dependency> <groupId>org.apache.calcite</groupId> <artifactId>calcite-kafka</artifactId> <version>1.28.0</version> </dependency> 测试代码 import java.sql.Connection; import java.sql.DriverMan…

【时间之外】IT人求职和创业应知【36】-肖申克的救赎

目录 新闻一&#xff1a;信息技术应用创新产业大会在深圳开幕 新闻二&#xff1a;人工智能与大数据融合应用成为创业新热点 新闻三&#xff1a;云计算与边缘计算协同发展推动IT行业创新 认知和思考决定了你的赚钱能力。以下是今天可能引起你思考的热点新闻&#xff1a; 新闻…

python高级之简单爬虫实现

一、前言 场景1&#xff1a;一个网络爬虫&#xff0c;顺序爬取一个网页花了一个小时&#xff0c;采用并发下载就减少到了20分钟。 场景2&#xff1a;一个应用软件优化前每次打开网页需要3秒&#xff0c;采用异步并发提升到了200毫秒。 假设一个工程的工作量为100&#xff0c…

01_MinIO部署(Windows单节点部署/Docker化部署)

单节点-Windows环境安装部署 在Windows环境安装MinIO&#xff0c;主要包含两个东西&#xff1a; MinIO Server&#xff08;minio.exe&#xff09;&#xff1a;应用服务本身MinIO Client&#xff08;mc.exe&#xff09;&#xff1a;MinIO客户端工具&#xff08;mc&#xff09;…

数据分析24.11.13

Excel 函数 求和 函数 sum() sumif() SUMIF(range, criteria, [sum_range]) sumifs() average() count() max() min() 逻辑 函数 if() iferror() 查询函数 VLOOKUP()

已有docker增加端口号,不用重新创建Docker

已有docker增加端口号&#xff0c;不用重新创建Docker 1. 整体描述2. 具体实现2.1 查看容器id2.2 停止docker服务2.3 修改docker配置文件2.4 重启docker服务 3. 总结 1. 整体描述 docker目前使用的非常多&#xff0c;但是每次更新都需要重新创建docker&#xff0c;也不太方便&…

java itext后端生成pdf导出

public CustomApiResult<String> exportPdf(HttpServletRequest request, HttpServletResponse response) throws IOException {// 防止日志记录获取session异常request.getSession();// 设置编码格式response.setContentType("application/pdf;charsetUTF-8")…

计算机前沿技术-人工智能算法-大语言模型-最新研究进展-2024-11-04

计算机前沿技术-人工智能算法-大语言模型-最新研究进展-2024-11-04 目录 文章目录 计算机前沿技术-人工智能算法-大语言模型-最新研究进展-2024-11-04目录1. Alopex: A Computational Framework for Enabling On-Device Function Calls with LLMs摘要&#xff1a;研究背景&…

NLP论文速读(谷歌出品)|缩放LLM推理的自动化过程验证器

论文速读|Rewarding Progress: Scaling Automated Process Verifiers for LLM Reasoning 论文信息&#xff1a; 简介&#xff1a; 这篇论文探讨了如何提升大型语言模型&#xff08;LLM&#xff09;在多步推理任务中的性能。具体来说&#xff0c;它试图解决的问题是现有的基于结…

k-近邻算法(K-Nearest Neighbors, KNN)详解:机器学习中的经典算法

✅作者简介&#xff1a;2022年博客新星 第八。热爱国学的Java后端开发者&#xff0c;修心和技术同步精进。 &#x1f34e;个人主页&#xff1a;Java Fans的博客 &#x1f34a;个人信条&#xff1a;不迁怒&#xff0c;不贰过。小知识&#xff0c;大智慧。 &#x1f49e;当前专栏…

Debezium-MySqlConnectorTask

文章目录 概要整体架构流程技术名词解释技术细节小结 概要 MySqlConnectorTask&#xff0c;用于读取MySQL的二进制日志并生成对应的数据变更事件 整体架构流程 技术名词解释 数据库模式&#xff08;Database Schema&#xff09; 数据库模式是指数据库中数据的组织结构和定义&…

SDF,一个从1978年运行至今的公共Unix Shell

关于SDF 最近发现了一个很古老的公共Unix Shell服务器&#xff0c;这个项目从1978年运行至今&#xff0c;如果对操作系统&#xff0c;对Unix感兴趣&#xff0c;可以进去玩一玩体验一下 SDF Public Access UNIX System - Free Shell Account and Shell Access 注册方式 我一…

逆向攻防世界CTF系列41-EASYHOOK

逆向攻防世界CTF系列41-EASYHOOK 看题目是一个Hook类型的&#xff0c;第一次接触&#xff0c;虽然学过相关理论&#xff0c;可以看我的文章 Hook入门(逆向)-CSDN博客 题解参考&#xff1a;https://www.cnblogs.com/c10udlnk/p/14214057.html和攻防世界逆向高手题之EASYHOOK-…

C# 面向对象

C# 面向对象编程 面向过程&#xff1a;一件事情分成多个步骤来完成。 把大象装进冰箱 (面向过程化设计思想)。走一步看一步。 1、打开冰箱门 2、把大象放进冰箱 3、关闭冰箱门 面向对象&#xff1a;以对象作为主体 把大象装进冰箱 1、抽取对象 大象 冰箱 门 &#xff0…

【AI图像生成网站Golang】项目架构

AI图像生成网站 目录 一、项目介绍 二、雪花算法 三、JWT认证与令牌桶算法 四、项目架构 五、图床上传与图像生成API搭建 六、项目测试与调试(等待更新) 四、项目架构 本项目的后端基于Golang和Gin框架开发&#xff0c;主要包括的模块有&#xff1a; backend/ ├── …