多线程和多进程的快速入门
多线程和多进程的快速入门
学习自:莫烦Python www.mofanpy.com
Threading - 多线程运算python程序
多线程的简单理解:把数据分成很多段,将每一段数据放入一个线程,将所有的线程同时开始,大大的节省了运算时间。相当于:请一个人来工作一件事和请很多人来工作一件事
Threading 可以分配python分批量在同一时间做事情,但是Threading只能是在一个py脚本中
添加一个线程的案例
import threading#def main():
# print(threading.active_count()) # 查看现在激活线程的数量
# print(threading.enumerate()) # 查看当前的threading都是什么
# print(threading.current_thread()) # 查看我运行这个函数程序的时候 对应的threading是什么def thread_job():print('This is a thread of %s' % threading.current_thread()) # 查看我运行这个函数程序的时候 对应的threading是什么def main():thread = threading.Thread(target=thread_job,) # 添加线程 这个线程做什么由target指定thread.start() # 添加一个线程后,要启动线程,才能让这个线程开始工作if __name__ == '__main__':main()
程序运行的结果为:
This is a thread of <Thread(Thread-1, started 6300)>
threading中的join的功能
由于多线程是同石进行运行的线程任务,如果某些时刻你想等待所有的线程都运行完,然后开始某些操作,这个时候需要在这个操作前对每个线程使用join操作
join操作是等待threading线程运行完
import threading
import time
def thread_job():print('T1 start\n')for i in range(10): time.sleep(0.1) # 睡一秒 print('T1 finish\n')def T2_job():print('T2 start\n')print('T2 finish\n')def main():added_thread = threading.Thread(target=thread_job, name='T1') # name为给线程命名thread2 = threading.Thread(target=T2_job, name='T2')added_thread.start()thread2.start()thread2.join()added_thread.join()print('all done\n')if __name__ == '__main__':main()
不加join的结果如下:
T1 startT2 start
all doneT2 finishT1 finish
加join的结果如下:
T1 startT2 startT2 finishT1 finishall done
多线程搭配Queue功能
多线程无返回值,所以要把运算出来的结果放在一个长的队列中,对每一个线程的队列到主线程中拿出来,以便做继续的运算。
import threading
import time
from queue import Queuedef job(l,q):# 对每一个列表中的值做平方运算for i in range(len(l)):l[i] = l[i]**2q.put(l)def multithreading():q = Queue() # 定义队列threads = [] # 用来存储所有的线程data = [[1,2,3],[3,4,5],[4,4,4],[5,5,5]]for i in range(4): # 定义四个线程 计算大列表中的四个小列表t = threading.Thread(target=job, args=(data[i], q)) # args用来给线程 传递参数t.start() # 启动线程threads.append(t) # 将每个小列表的计算线程 存储到线程列表中for thread in threads: thread.join() # 等到所有的线程运行完 再继续操作results = []for _ in range(4): results.append(q.get()) # 将每个线程运算的结果 保存print(results)if __name__ == '__main__':multithreading()
该程序的结果如下:
[[1, 4, 9], [9, 16, 25], [16, 16, 16], [25, 25, 25]]
多线程的效率分析
多线程的全局控制并不是把任务平均的分配个每一个线程 ,python只能让一个线程在某一时刻运算一个东西,然后不停的切换线程,让你误以为这些线程是在相同时刻在运算。 (学过操作系统应该会很容易理解多线程的并发运算)
下面实力代码中:
normal方法:对四倍的l列表执行累加运算
multithreading多线程方法:将四倍的l列表分为四份,用四个多线程同时处理
import threading
from queue import Queue
import copy
import timedef job(l, q):res = sum(l)q.put(res)def multithreading(l):q = Queue()threads = []for i in range(4):t = threading.Thread(target=job, args=(copy.copy(l), q), name='T%i' % i)t.start()threads.append(t)[t.join() for t in threads]total = 0for _ in range(4):total += q.get()print(total)def normal(l):total = sum(l)print(total)if __name__ == '__main__':l = list(range(1000000))s_t = time.time()normal(l*4)print('normal: ',time.time()-s_t)s_t = time.time()multithreading(l)print('multithreading: ', time.time()-s_t)
程序的执行结果:
1999998000000
normal: 0.08538269996643066
1999998000000
multithreading: 0.08719158172607422
用了多线程比未用多线程的耗时反而多了
多线程与lock锁
锁的用法:当第一个线程处理完这一批数据得到一个初步的结果,然后再把这个结果拿去给第二个线程处理,这个时候就需要锁住第一个线程,等他处理完,再开始第二个线程
在要进行上锁的程序的前后设置锁
import threadingdef job1():global A, locklock.acquire() # 在要进行上锁的程序前 设置锁for i in range(10): # 对A进行10次累加1A += 1print('job1', A)lock.release() # 在要进行上锁的程序后 设置锁def job2():global A, locklock.acquire()for i in range(10): # 对A进行10次累加10A += 10print('job2', A)lock.release()if __name__ == '__main__':lock = threading.Lock() # 定义锁A = 0 # 定义一个全局变量 模拟共享内存t1 = threading.Thread(target=job1)t2 = threading.Thread(target=job2)t1.start()t2.start()t1.join()t2.join()
不加锁的程序结果: 两个线程同时运行,结果上为交替对A进行操作
job1 1
job1 2
job1 13
job2 12
job1 14
job2 24
job1 25
job2 35
job1 36
job2 46
job1 47
job2 57
job1 58
job2 68
job1 69
job2 79
job1 80
job2 90
job2 100
job2 110
加锁的程序结果: job1先上锁 待程序运行完后 解锁。此时job2再上锁 待程序运行完后 解锁
job1 1
job1 2
job1 3
job1 4
job1 5
job1 6
job1 7
job1 8
job1 9
job1 10
job2 20
job2 30
job2 40
job2 50
job2 60
job2 70
job2 80
job2 90
job2 100
job2 110
Multiprocessing - 多进程运算python程序
运用多核CPU处理器CPU运算python程序,一般只会用一个核来处理程序,但是现代计算器的处理器一般都是多核,如果不用白白的浪费,可以将其运用起来加速程序的处理。
多线程实际上还是同一个时间处理一个线程(并发轮转调度),而多核完全避免了这种情况,它会把任务平均分配给每一个核,每一个核都有单独的运算空间和运算能力,多核从一定程度上避免了多线程劣势。
创建进程
import multiprocessing as mpdef job(q):print("进程创建", q)if __name__ == '__main__':p1 = mp.Process(target=job, args=(q,))p1.start()
进程与Queue输出
将每一个核运算出来的结果放入到队列Queue中,等到所有的核运算完成后,再将结果从队列中取出,以便后续操作
import multiprocessing as mpdef job(q):res = 0for i in range(1000):res += i+i**2+i**3q.put(res) # 将运算后的值操作放入到队列if __name__ == '__main__':q = mp.Queue() # 定义队列p1 = mp.Process(target=job, args=(q,)) # 注意args 即使只有一个参数 也要写成(q,) 不然会报错 p2 = mp.Process(target=job, args=(q,))p1.start()p2.start()p1.join()p2.join()res1 = q.get() # 从队列中获取值res2 = q.get()print(res1+res2)
运行结果为:499667166000
进程池
进程池就是把所有要运行的东西放到一个池子里,python自己解决如何分配这些进程,如何分配运行出来的结果。
import multiprocessing as mpdef job(x): # 平方操作return x*xdef multicore():pool = mp.Pool(processes=2) # 默认的是你所有的核心, processes是指定想用的核的数量res = pool.map(job, range(10)) # map 将range(10) 交给job,并将结果返回print(res)res = pool.apply_async(job, (2,)) # 只传入一个值给job 如果输入的是(2,3,4,5)会报错,因为只能传入一个值print(res.get()) # 使用get获取multi_res =[pool.apply_async(job, (i,)) for i in range(10)] # 利用迭代器 获取对多个值操作的结果print([res.get() for res in multi_res]) # 利用列表迭代获取if __name__ == '__main__':multicore()
程序运行的结果:
[0, 1, 4, 9, 16, 25, 36, 49, 64, 81]
4
[0, 1, 4, 9, 16, 25, 36, 49, 64, 81]
多进程使用shared memory共享内存
为什么使用共享内存,不用全局变量?
因为多进程中传入全局变量给每个cpu,多进程对全局变量进行操作后传给其它进程是行不通的
import multiprocessing as mpvalue = mp.Value('i', 1) # i是整数 d是double小数 f是float小数等等
array = mp.Array('i', [1, 2, 3, 4]) # 只能是一维列表,不能是多维
value和array可以被每一个核读取,加载到内存
多进程与lock锁
锁的应用:
import multiprocessing as mp
import timedef job(v, num, l):l.acquire()for _ in range(10):time.sleep(0.1)v.value += numprint(v.value)l.release()def multicore(): l = mp.Lock() # 实例化锁v = mp.Value('i', 0) # 设立共享内存变量p1 = mp.Process(target=job, args=(v, 1, l)) p2 = mp.Process(target=job, args=(v, 3, l))p1.start()p2.start()p1.join()p2.join()if __name__ == '__main__':multicore()
加锁的结果为:
前面程序依次+1 后面程序依次+3
不加锁的结果为:
3 4 7 8 11 12这样两个多进程交替打印结果
多线程、多进程以及函数的效率对比
import multiprocessing as mp
import threading as td
import timedef job(q):res = 0for i in range(1000000):res += i+i**2+i**3q.put(res) # queuedef multicore():q = mp.Queue()p1 = mp.Process(target=job, args=(q,))p2 = mp.Process(target=job, args=(q,))p1.start()p2.start()p1.join()p2.join()res1 = q.get()res2 = q.get()print('multicore:' , res1+res2)def normal():res = 0for _ in range(2):for i in range(1000000):res += i+i**2+i**3print('normal:', res)def multithread():q = mp.Queue()t1 = td.Thread(target=job, args=(q,))t2 = td.Thread(target=job, args=(q,))t1.start()t2.start()t1.join()t2.join()res1 = q.get()res2 = q.get()print('multithread:', res1+res2)if __name__ == '__main__':st = time.time()normal()st1= time.time()print('normal time:', st1 - st)multithread()st2 = time.time()print('multithread time:', st2 - st1)multicore()print('multicore time:', time.time()-st2)
运行的结果:
# 不用进程和线程
normal: 499999666667166666000000
normal time: 0.75795578956604
# 多线程
multithread: 499999666667166666000000
multithread time: 0.7419922351837158
# 多进程
multicore: 499999666667166666000000
multicore time: 0.4487142562866211
多进程运算的时间明显由于另外两个,多线程的运算与什么都不做时间差不多,说明多线程对于某些运算还是存在明显的短板
相关文章:
多线程和多进程的快速入门
多线程和多进程的快速入门 学习自:莫烦Python www.mofanpy.com Threading - 多线程运算python程序 多线程的简单理解:把数据分成很多段,将每一段数据放入一个线程,将所有的线程同时开始,大大的节省了运算时间。相…...
【TensorFlow深度学习】经典卷积网络架构回顾与分析
经典卷积网络架构回顾与分析 经典卷积网络架构回顾与分析:从AlexNet到ResNet、VGGLeNet、ResNet、DenseNet的深度探索AlexNet ——深度学习的破冰点火VGGNet — 简洁的美ResNet — 深持续深度的秘钥DenseNet — 密集大成塔实战代码示例:ResNet-50模型结语…...

Salesforce推出Einstein 1 Studio:用于自定义Einstein Copilot并将人工智能嵌入任何CRM应用程序的低代码人工智能工具
一、关键要点 1. Salesforce管理员和开发人员现在可以在每个Salesforce应用程序和工作流程中构建、定制和嵌入人工智能,包括Einstein Copilot。 2. Einstein 1 Studio与数据云深度集成,通过对客户数据和元数据的全面理解,解锁并统一被捕获的…...

点赋科技:建设智能饮品高地,打造数字化产业先锋
在当今数字化时代的浪潮中,点赋科技以其敏锐的洞察力和卓越的创新能力,致力于建设智能饮品高地,打造数字化产业先锋。 点赋深知智能饮品机对于推动社会进步和满足人们日益增长的需求的重要性。因此,他们投入大量资源和精力&#x…...
ORACLE RAC的一些基本理论知识
一 . Oracle RAC 的发展历程 1. Oracle Parallel Server (OPS) 早期阶段:Oracle 6 和 7 Oracle Parallel Server(OPS)是 Oracle RAC 的前身。 通过多个实例并行访问同一个数据库来提高性能。 共享磁盘架构,利用分布式锁管理&am…...

CMake的作用域:public/private/interface
在 CMake 中,public、private和 interface是用来指定目标属性的作用域的关键字,这三个有什么区别呢?这些关键字用于控制属性的可见性和传递性,影响了目标之间的依赖关系和属性传递。 public 如果在一个目标上使用 public关键字时…...

设计模式基础知识点(七大原则、UML类图)
Java设计模式(设计模式七大原则、UML类图) 设计模式的目的设计模式七大原则单一职能原则(SingleResponsibility)接口隔离原则(InterfaceSegreation)依赖倒转原则(DependenceInversion࿰…...

Android开机动画的结束过程BootAnimation(基于Android10.0.0-r41)
文章目录 Android 开机动画的结束过程BootAnimation(基于Android10.0.0-r41) Android 开机动画的结束过程BootAnimation(基于Android10.0.0-r41) 路径frameworks/base/cmds/bootanimation/bootanimation_main.cpp init进程把我们的BootAnimation的二进制文件拉起来了…...

微软远程连接工具:Microsoft Remote Desktop for Mac 中文版
Microsoft Remote Desktop 是一款由微软开发的远程桌面连接软件,它允许用户从远程地点连接到远程计算机或虚拟机,并在远程计算机上使用桌面应用程序和文件。 下载地址:https://www.macz.com/mac/5458.html?idOTI2NjQ5Jl8mMjcuMTg2LjEyNi4yMz…...

【安规介绍】
文章目录 一、基础知识安规上的六类危险的防护:安全电压漏电流接触电流能量问题:火灾问题:热问题结构问题阻燃等级绝缘等级:对接地系统的要求:结构要求:电气要求: 二、设计的关键电气绝缘距离电气爬电距离:…...
[sylar]后端学习:配置环境(一)
1.介绍 基于sylar大神的C高性能后端网络框架来进行环境配置和后续学习。网站链接:sylar的Linux环境配置 2.下载 按照视频进行下载,并进行下载,并最好还要下载一个vssh的软件。可以直接在网上搜索即可。 sylar_环境配置,vssh下…...

XDMA原理及其应用和发展
XDMA原理 XDMA的主要原理是通过直接访问主机内存,实现数据的快速传输。在传统的DMA(Direct Memory Access)技术中,数据传输需要经过CPU的干预,而XDMA可以绕过CPU,直接将数据从外设读取到主机内存或者从主机…...

携程梁建章:持续投资创新与AI,开启旅游行业未来增长
5月30至31日,携程集团在上海和张家界举办Envision 2024全球合作伙伴大会,邀请超50个国家和地区的1600余名外籍旅游业嘉宾与会,共同探讨中国跨境旅游市场发展机遇,讲好中国故事。 携程国际业务增速迅猛,创新与AI解锁未…...

【网络安全的神秘世界】在win11搭建pikachu靶场
🌝博客主页:泥菩萨 💖专栏:Linux探索之旅 | 网络安全的神秘世界 | 专接本 下载pikachu压缩包 https://github.com/zhuifengshaonianhanlu/pikachu 下载好的pikachu放在phpstudy_pro/www目录下 创建pikachu数据库 打开phpstudy软件…...

基于Java的零食管理系统的设计与实现(论文+源码)_kaic
摘 要 随着科技的进步,以及网络的普及,都为人们的生活提供了极大的方便。因此,在管理”三姆”宿舍在线零食商店时,与现代的网络联系起来是非常必要的,本次设计的系统在研发过程中应用到了Java技术,这在一定…...

【案例实操】银河麒麟桌面操作系统实例分享,V10SP1重启后网卡错乱解决方法
1.问题现象 8 个网口, 命名从 eth1 开始到 eth8。 目前在系统 grub 里面加了 net.ifnames0 biosdevname0 参数, 然后在 udev 规则中加了一条固定网卡和硬件 pci 设备号的规则文件。 最后在 rc.local 中加了两条重新安装网卡驱动的命令( rmmod…...
初级前端开发岗
定位: 日常任务的辅助执行者,前端基础建设的参与者。 素质要求: 是否遵循部门敏捷流程、规范、P0制度;具备良好的沟通和协作能力;负责日常迭代任务的落地执行;拥有较强的执行力,能够灵活解决问题; 职责:…...

颠仆流离学二叉树2 (Java篇)
本篇会加入个人的所谓鱼式疯言 ❤️❤️❤️鱼式疯言:❤️❤️❤️此疯言非彼疯言 而是理解过并总结出来通俗易懂的大白话, 小编会尽可能的在每个概念后插入鱼式疯言,帮助大家理解的. 🤭🤭🤭可能说的不是那么严谨.但小编初心是能让更多人…...

柏林自由大学研究团队《Ecology Letters 》揭示AMF在植物对全球变化响应的作用
全球环境变化正在影响陆生植物生长。植物已经进化出各种策略来应对这些挑战,其中之一是与丛枝菌根真菌(AMF)形成共生关系(高达80%的陆生植物物种)。AMF为寄主植物提供各种益处,例如营养吸收、耐受性、食草动物防御和抗病能力,以换取糖和脂质(…...

libevent源码跨平台编译(windows/macos/linux)
1.windows编译: 克隆: git clone https://github.com/libevent/libevent.git 克隆成功 生成makefile 生成成功 默认不支持OpenSSL,MbedTLS,ZLIB这三个库 编译: cmake --build . --config release...

为什么需要建设工程项目管理?工程项目管理有哪些亮点功能?
在建筑行业,项目管理的重要性不言而喻。随着工程规模的扩大、技术复杂度的提升,传统的管理模式已经难以满足现代工程的需求。过去,许多企业依赖手工记录、口头沟通和分散的信息管理,导致效率低下、成本失控、风险频发。例如&#…...

页面渲染流程与性能优化
页面渲染流程与性能优化详解(完整版) 一、现代浏览器渲染流程(详细说明) 1. 构建DOM树 浏览器接收到HTML文档后,会逐步解析并构建DOM(Document Object Model)树。具体过程如下: (…...

Nuxt.js 中的路由配置详解
Nuxt.js 通过其内置的路由系统简化了应用的路由配置,使得开发者可以轻松地管理页面导航和 URL 结构。路由配置主要涉及页面组件的组织、动态路由的设置以及路由元信息的配置。 自动路由生成 Nuxt.js 会根据 pages 目录下的文件结构自动生成路由配置。每个文件都会对…...

用机器学习破解新能源领域的“弃风”难题
音乐发烧友深有体会,玩音乐的本质就是玩电网。火电声音偏暖,水电偏冷,风电偏空旷。至于太阳能发的电,则略显朦胧和单薄。 不知你是否有感觉,近两年家里的音响声音越来越冷,听起来越来越单薄? —…...

FFmpeg:Windows系统小白安装及其使用
一、安装 1.访问官网 Download FFmpeg 2.点击版本目录 3.选择版本点击安装 注意这里选择的是【release buids】,注意左上角标题 例如我安装在目录 F:\FFmpeg 4.解压 5.添加环境变量 把你解压后的bin目录(即exe所在文件夹)加入系统变量…...

(一)单例模式
一、前言 单例模式属于六大创建型模式,即在软件设计过程中,主要关注创建对象的结果,并不关心创建对象的过程及细节。创建型设计模式将类对象的实例化过程进行抽象化接口设计,从而隐藏了类对象的实例是如何被创建的,封装了软件系统使用的具体对象类型。 六大创建型模式包括…...
c# 局部函数 定义、功能与示例
C# 局部函数:定义、功能与示例 1. 定义与功能 局部函数(Local Function)是嵌套在另一个方法内部的私有方法,仅在包含它的方法内可见。 • 作用:封装仅用于当前方法的逻辑,避免污染类作用域,提升…...
6个月Python学习计划 Day 16 - 面向对象编程(OOP)基础
第三周 Day 3 🎯 今日目标 理解类(class)和对象(object)的关系学会定义类的属性、方法和构造函数(init)掌握对象的创建与使用初识封装、继承和多态的基本概念(预告) &a…...
绕过 Xcode?使用 Appuploader和主流工具实现 iOS 上架自动化
iOS 应用的发布流程一直是开发链路中最“苹果味”的环节:强依赖 Xcode、必须使用 macOS、各种证书和描述文件配置……对很多跨平台开发者来说,这一套流程并不友好。 特别是当你的项目主要在 Windows 或 Linux 下开发(例如 Flutter、React Na…...
Java并发编程实战 Day 11:并发设计模式
【Java并发编程实战 Day 11】并发设计模式 开篇 这是"Java并发编程实战"系列的第11天,今天我们聚焦于并发设计模式。并发设计模式是解决多线程环境下常见问题的经典解决方案,它们不仅提供了优雅的设计思路,还能显著提升系统的性能…...