多线程和多进程的快速入门

多线程和多进程的快速入门

学习自:莫烦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

多进程运算的时间明显由于另外两个,多线程的运算与什么都不做时间差不多,说明多线程对于某些运算还是存在明显的短板

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

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

相关文章

如何利用exceljs将data数据导出表格实现日期去重,同时保留对应日期的每一列数据

const data [{ deviceId: 1, name: "B相电压", signalTypeId: 1, ts: "2024-05-13 12:10:06", unit: "kV", 1: 39.37936, value:39.37936, },{ deviceId: 1, name: "A相电压", signalTypeId: 2, ts: "2024-05-13 12:11:06"…

springboot基本使用十二(PageHelper分页查询)

引入依赖&#xff1a; <dependency><groupId>com.github.pagehelper</groupId><artifactId>pagehelper-spring-boot-starter</artifactId><version>1.3.0</version> </dependency> 通个PageHelper.startPage(page,pageSize)方…

代码随想录算法训练营day42 | 62.不同路径、63. 不同路径 II

62.不同路径 确定dp数组及其下标的含义&#xff1a;dp[i][j]代表机器人到达i行j列时不同的路径数确定递推公式&#xff1a;dp[i][j] dp[i-1][j] dp[i][j-1]dp数组的初始化&#xff1a;dp[0][j] 1 dp[i][0] 1确定遍历顺序&#xff1a;从前向后举例推导dp数组 class Soluti…

nuxt3的一些知识点,持续更新

1.npx nuxilatest init xx 命令执行失败 ERROR Error: Failed to download template from registry: Failed to download https://raw.githubusercontent.com/nuxt/starter/templates/templates/v3.json: TypeError: fetch failed 解决办法&#xff1a;host加上 185.199.108.…

“仿RabbitMQ实现消息队列”---整体架构与模块说明

顾得泉&#xff1a;个人主页 个人专栏&#xff1a;《Linux操作系统》 《C从入门到精通》 《LeedCode刷题》 键盘敲烂&#xff0c;年薪百万&#xff01; 一、概念性框架理解 我们主要实现的内容&#xff1a; 1.Broker服务器&#xff1a;消息队列服务器&#xff08;服务端&…

连通块中点的数量-java

本次我们通过连通块中点的数量来加深我们对并查集的基本操作和原理&#xff0c;并且知道如何在并查集中添加附属信息。 目录 前言☀ 一、连通块中点的数量☀ 二、算法思路☀ 1.无向图&#x1f319; 2.在a b之间连一条边&#xff0c;a b可能相等&#x1f319; 3.询问a和b是否在一…

Apache POI对Excel进行读写操作

1、什么是Apache POI ​ Apache POI 是一个处理Miscrosoft Office各种文件格式的开源项目。简单来说就是&#xff0c;我们可以使用 POI 在 Java 程序中对Miscrosoft Office各种文件进行读写操作。一般情况下&#xff0c;POI 都是用于操作 Excel 文件。 Apache POI 的应用场景&…

【为什么 Google Chrome 打开网页有时极慢?尤其是国内网站,如知网等】

要通过知网搜一点资料&#xff0c;发现怎么都打不开。而且B站&#xff0c;知乎这些速度也变慢了&#xff01;已经检查过确定不是网络的问题。 清空了记录&#xff0c;清空了已接受Cookie&#xff0c;清空了缓存内容……没用&#xff01;&#xff01;&#xff01; 不断搜索&am…

注意力机制详解

引言 在阅读一篇文章时&#xff0c;我们的大脑并不平等地处理每一个字词&#xff0c;而是根据上下文自动筛选出核心信息进行深入理解。注意力机制正是借鉴了这一生物学灵感&#xff0c;使得机器学习模型能够动态地分配其“注意力”资源&#xff0c;针对不同的输入部分赋予不同…

大数据信用报告分析和评估有什么意义

大数据信用这个词在现在已经是很常见的了&#xff0c;只要是申贷的朋友对它就不陌生&#xff0c;在明面上的信用资质刚刚满足审核要求&#xff0c;但又要把控风险的时候&#xff0c;这个时候大数据信用就会作为风控机构交叉核查的重要依据。那你知道大数据信用报告分析和评估有…

代码随想录——二叉搜索树的最小绝对差(Leetcode530)

题目链接 层序遍历 /*** Definition for a binary tree node.* public class TreeNode {* int val;* TreeNode left;* TreeNode right;* TreeNode() {}* TreeNode(int val) { this.val val; }* TreeNode(int val, TreeNode left, TreeNode right) …

if constexpr实现条件编译

#include <iostream>// 利用if constexpr实现了条件编译 template<typename T1, typename T2> void test_func() {if constexpr (std::is_same_v<T1, T2>) {std::cout << "hit stage\n";} else {std::cout << "miss\n";} }i…

Microsoft的Copilot现已登陆Telegram

每周跟踪AI热点新闻动向和震撼发展 想要探索生成式人工智能的前沿进展吗&#xff1f;订阅我们的简报&#xff0c;深入解析最新的技术突破、实际应用案例和未来的趋势。与全球数同行一同&#xff0c;从行业内部的深度分析和实用指南中受益。不要错过这个机会&#xff0c;成为AI领…

数据结构复习指导之插入排序

文章目录 排序 考纲内容 知识框架 复习提示 1.排序的基本概念 1.1排序的定义 2.插入排序 2.1直接插入排序 2.2折半插入排序 2.3希尔排序 知识回顾 排序 考纲内容 &#xff08;一&#xff09;排序的基本概念 &#xff08;二&#xff09;插入排序 直接插…

多线程基础知识-09

ThreadLocal 是什么 ThreadLocal 是 Java 中的一个类&#xff0c;它提供了线程局部变量的功能。每个 ThreadLocal 对象都维护了一个线程私有的变量副本&#xff0c;不同线程之间无法访问彼此的副本。这样可以保证每个线程都能够独立地操作自己的变量副本&#xff0c;而不会发生…

内网不能访问域名怎么办?

在网络应用中&#xff0c;我们常常遇到内网不能访问域名的问题。这是由于内网环境限制导致的&#xff0c;内网无法直接连接到公网&#xff0c;因而无法访问互联网上的域名。我们可以利用一些特殊技术和工具来解决这个问题。 天联组网技术的应用 天联组网是一种非常受欢迎的解决…

Java实战项目开发的个人技巧分享

前言 笔者目前从事一线 Java 开发今年是第 3 个年头了&#xff0c;从 0-1的 SaaS、PaaS 的项目做过&#xff0c;多租户下定制化开发项目也做过&#xff0c;项目的 PM 也做过... 在实际的开发中积累了一些技巧和经验&#xff0c;包括线上 bug 处理、日常业务开发、团队开发规范…

NetApp财季报告亮点:全闪存阵列需求强劲,云计算收入增长放缓但AI领域前景乐观

在最新的财季报告中&#xff0c;NetApp的收入因全闪存阵列的强劲需求而显著增长。截至2024年4月26日的2024财年第四季度&#xff0c;NetApp的收入连续第三个季度上升&#xff0c;达到了16.7亿美元&#xff0c;较前一年同期增长6%&#xff0c;超出公司指导中值。净利润为2.91亿美…

前端开发:$nextTick()的使用及原理

目录 前言 $nextTick()的概念 $nextTick()的用法和原理 1、$nextTick()用法 2、$nextTick()原理 $nextTick()的具体使用示例 拓展&#xff1a;面试中考察$nextTick()的底层原理 最后 前言 在前端开发中&#xff0c;涉及到JS原生的使用原理是非常重要的知识点&#xff0…

Kafka 消息保留策略及其影响详解

目录 Kafka 消息保留策略及其影响详解消息保留策略超过保留时间的消息删除过程删除过程对正在消费的消息和偏移量的影响不同保留时间设置的区别总结 博客示例题目&#xff1a;详解 Kafka 消息保留策略及其影响消息保留策略超过保留时间的消息删除过程删除过程对正在消费的消息和…