浅谈对进程的理解

一、多任务的概念

1、举个栗子

思考:我们在使用网盘下载资料的时候,为什么要多个任务同时下载呢?

答:多个任务同时执行可以大大提高程序的执行效率

2、提出问题

问题:利用我们目前所学的技术,我们能否实现多任务操作呢?

答:不能,因为之前所写的程序都是单任务的,也就是说一个函数或者方法执行完成 , 另外一个函数或者方法才能执行。要想实现多个任务同时执行就需要使用多任务。多任务的最大好处是充分利用CPU资源,提高程序的执行效率。

3、什么是多任务

多任务是指在同一时间内执行多个任务。

例如: 现在电脑安装的操作系统都是多任务操作系统,可以同时运行着多个软件。

4、多任务的两种表现形式

① 并发

② 并行

5、并发操作

并发:在一段时间内交替去执行多个任务。

例如:对于单核cpu处理多任务,操作系统轮流让各个任务交替执行,假如:软件1执行0.01秒,切换到软件2,软件2执行0.01秒,再切换到软件3,执行0.01秒……这样反复执行下去, 实际上每个软件都是交替执行的 . 但是,由于CPU的执行速度实在是太快了,表面上我们感觉就像这些软件都在同时执行一样 . 这里需要注意单核cpu是并发的执行多任务的。

6、并行操作

并行:在一段时间内真正的同时一起执行多个任务。

对于多核cpu处理多任务,操作系统会给cpu的每个内核安排一个执行的任务,多个内核是真正的一起同时执行多个任务。这里需要注意多核cpu是并行的执行多任务,始终有多个任务一起执行。

二、进程的概念

1、程序中实现多任务的方式

在Python中,想要实现多任务可以使用==多进程==来完成。

2、进程的概念

进程(Process)是资源分配的最小单位,它是操作系统进行资源分配和调度运行的基本单位,通俗理解:一个正在运行的程序就是一个进程。

例如:正在运行的qq , 微信等 他们都是一个进程。

注: 一个程序运行后至少有一个进程

3、多进程的作用

☆ 未使用多进程

思考:

​ 图中是一个非常简单的程序 , 一旦运行hello.py这个程序 , 按照代码的执行顺序 , func_a函数执行完毕后才能执行func_b函数 . 如果可以让func_a和func_b同时运行 , 显然执行hello.py这个程序的效率会大大提升 .

☆ 使用了多进程

三、多进程完成多任务

1、多进程完成多任务

① 导入进程包
import multiprocessing
​
② 通过进程类创建进程对象 
进程对象 = multiprocessing.Process() 
​
③ 启动进程执行任务
进程对象.start()

2、通过进程类创建进程对象

进程对象 = multiprocessing.Process([group [, target=任务名 [, name]]])

参数说明:

参数名说明
target执行的目标任务名,这里指的是函数名(方法名)
name进程名,一般不用设置
group进程组,目前只能使用None

3、进程创建与启动的代码

边听音乐边敲代码:

import multiprocessing
import time
​
​
def music():for i in range(3):print('听音乐...')time.sleep(0.2)
​
​
def coding():for i in range(3):print('敲代码...')time.sleep(0.2)
​
if __name__ == '__main__':music_process = multiprocessing.Process(target=music)coding_process = multiprocessing.Process(target=coding)
​music_process.start()coding_process.start()

4、进程执行带有参数的任务

Process([group [, target [, name [, args [, kwargs]]]]])

参数说明:

参数名说明
args以元组的方式给执行任务传参,args表示调用对象的位置参数元组,args=(1,2,'anne',)
kwargs以字典方式给执行任务传参,kwargs表示调用对象的字典,kwargs={'name':'anne','age':18}

案例:args参数和kwargs参数的使用

import multiprocessing
import time
​
​
def music(num):for i in range(num):print('听音乐...')time.sleep(0.2)
​
​
def coding(count):for i in range(count):print('敲代码...')time.sleep(0.2)
​
​
music_process = multiprocessing.Process(target=music, args=(3, ))
coding_process = multiprocessing.Process(target=coding, kwargs={'count': 3})
​
music_process.start()
coding_process.start()

案例:多个参数传递

import multiprocessing
import time
​
​
def music(num, name):for i in range(num):print(name)print('听音乐...')time.sleep(0.2)
​
​
def coding(count):for i in range(count):print('敲代码...')time.sleep(0.2)
​
​
if __name__ == '__main__':music_process = multiprocessing.Process(target=music, args=(3, '多任务开始'))coding_process = multiprocessing.Process(target=coding, kwargs={'count': 3})
​music_process.start()coding_process.start()

四、获取进程编号

1、进程编号的作用

当程序中进程的数量越来越多时 , 如果没有办法区分主进程和子进程还有不同的子进程 , 那么就无法进行有效的进程管理 , 为了方便管理实际上每个进程都是有自己编号的。

2、两种进程编号

① 获取当前进程编号

getpid()

② 获取当前进程的父进程ppid = parent pid

getppid()

3、获取当前进程编号

import os
​
​
def work():# 获取当前进程的编号print('work进程编号', os.getpid())# 获取父进程的编号print('work父进程的编号', os.getppid())​
work()

案例:获取子进程编号

import multiprocessing
import time
import os
​
​
def music(num):print('music>> %d' % os.getpid())for i in range(num):print('听音乐...')time.sleep(0.2)
​
​
def coding(count):print('coding>> %d' % os.getpid())for i in range(count):print('敲代码...')time.sleep(0.2)
​
​
if __name__ == '__main__':music_process = multiprocessing.Process(target=music, args=(3, ))coding_process = multiprocessing.Process(target=coding, kwargs={'count': 3})
​music_process.start()coding_process.start()

案例:获取父进程与子进程编号

import multiprocessing
import time
import os
​
​
def music(num):print('music>> %d' % os.getpid())print('music主进程>> %d' % os.getppid())for i in range(num):print('听音乐...')time.sleep(0.2)
​
​
def coding(count):print('coding>> %d' % os.getpid())print('music主进程>> %d' % os.getppid())for i in range(count):print('敲代码...')time.sleep(0.2)
​
​
if __name__ == '__main__':print('主进程>> %d' % os.getpid())music_process = multiprocessing.Process(target=music, args=(3, ))coding_process = multiprocessing.Process(target=coding, kwargs={'count': 3})
​music_process.start()coding_process.start()

五、进程应用注意点

1、进程间不共享全局变量

实际上==创建一个子进程就是把主进程的资源进行拷贝产生了一个新的进程==,这里的主进程和子进程是互相独立的。

案例:

import multiprocessing
​
my_list = []
​
​
def write_data():for i in range(3):my_list.append(i)print('add:', i)print(my_list)
​
​
def read_data():print('read_data', my_list)
​
​
if __name__ == '__main__':# 创建写入数据进程write_process = multiprocessing.Process(target=write_data)# 创建读取数据进程read_process = multiprocessing.Process(target=read_data)
​# 启动进程执行相关任务write_process.start()time.sleep(1)read_process.start()

原理分析:

三个进程分别操作的都是自己进程里面的全局变量my_list, 不会对其它进程里面的全局变量产生影响,所以进程之间不共享全局变量,只不过进程之间的全局变量名字相同而已,但是操作的不是同一个进程里面的全局变量。

知识点小结:

创建子进程会对主进程资源进行拷贝,也就是说子进程是主进程的一个副本,好比是一对双胞胎,之所以进程之间不共享全局变量,是因为操作的不是同一个进程里面的全局变量,只不过不同进程里面的全局变量名字相同而已。

2、主进程与子进程的结束顺序

代码演示:

import multiprocessing
import time
​
​
# 工作函数
def work():for i in range(10):print('工作中...')time.sleep(0.2)
​
​
if __name__ == '__main__':# 创建子进程work_process = multiprocessing.Process(target=work)# 启动子进程work_process.start()
​# 延迟1stime.sleep(1)print('主进程执行完毕')

执行结果:

☆ 解决方案一:设置守护进程

import multiprocessing
import time
​
​
# 工作函数
def work():for i in range(10):print('工作中...')time.sleep(0.2)
​
​
if __name__ == '__main__':# 创建子进程work_process = multiprocessing.Process(target=work)# 设置守护主进程,主进程退出后子进程直接销毁,不再执行子进程中的代码work_process.daemon = True# 启动子进程work_process.start()
​# 延迟1stime.sleep(1)print('主进程执行完毕')

☆ 解决方案二:销毁子进程

import multiprocessing
import time
​
​
# 工作函数
def work():for i in range(10):print('工作中...')time.sleep(0.2)
​
​
if __name__ == '__main__':# 创建子进程work_process = multiprocessing.Process(target=work)# 启动子进程work_process.start()
​# 延迟1stime.sleep(1)# 让子进程直接销毁,表示终止执行, 主进程退出之前,把所有的子进程直接销毁就可以了work_process.terminate()print('主进程执行完毕')

提示: 以上两种方式都能保证主进程退出子进程销毁

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

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

相关文章

输入框验证数字类型

校验大于0的数,且小数点后最多为八位小数 let k /^(?!0(\.0)?$)\d(\.\d{1,8})?$/; console.log(k.test(0.00000001)); // true console.log(k.test(0.00000000)); // false console.log(k.test(0.12)); // true console.log(k.test(12.12)); // true输入0-1的数字&#xf…

【计算机考研】408算法大题怎么练?

先说结论:基础阶段学好各个数据结构与,重点是数组、链表、树、图。然后强化阶段突破算法提 在基础阶段,并不需要过于专门地练习算法。相反,基础阶段的重点应该放在对各种数据结构原理的深入理解上。在我个人的经验中,…

python--异常处理

异常处理 例一: try: #可能出现异常代码 except: #如果程序异常,则立刻进入这儿 [finally: #不管是否捕获异常,finally语法快必须要执行!!! #资源关闭,等各种非常重要的操作&…

HarmonyOS实战开发-如何使用 geolocation 实现获取当前位置经纬度

介绍 本示例使用 geolocation 实现获取当前位置的经纬度,然后通过 http 将经纬度作为请求参数,获取到该经纬度所在的城市。通过 AlphabetIndexer 容器组件实现按逻辑结构快速定位容器显示区域。 效果预览 使用说明 1.进入主页,点击国内热门城市,配送地址会更新为选择的城…

【Erlang】【RabbitMQ】Linux(CentOS7)安装Erlang和RabbitMQ

一、系统环境 查版本对应,CentOS-7,选择Erlang 23.3.4,RabbitMQ 3.9.16 二、操作步骤 安装 Erlang repository curl -s https://packagecloud.io/install/repositories/rabbitmq/erlang/script.rpm.sh | sudo bash安装 Erlang package s…

CAXA电子图版2019版 下载地址及安装教程

CAXA电子图板是一款由国内软件公司CAXA开发的专业CAD(计算机辅助设计)软件。它主要用于绘制和编辑各种类型的二维图纸和工程图纸,广泛应用于建筑、机械、电气和电子等行业。 CAXA电子图板具有以下主要功能和特点: 二维绘图&…

Godot 常用UI+布局容器简单介绍

文章目录 前言相关链接Canvasitem:画布Control:UI布局基类Container:布局容器基类AspectRatioContainer:伸缩居中布局BoxContainer:盒子布局ColorPicker:取色器 CenterContainer:不伸缩居中FlowContainer&a…

Java 那些诗一般的 数据类型 (下篇)

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

【RAG实践】Rerank,让大模型 RAG 更近一步

RAGRerank原理 上一篇【RAG实践】基于LlamaIndex和Qwen1.5搭建基于本地知识库的问答机器人 我们介绍了什么是RAG,以及如何基于LLaMaIndex和Qwen1.5搭建基于本地知识库的问答机器人,原理图和步骤如下: 这里面主要包括包括三个基本步骤&#…

MySQL数据库在Windows和Linux中各种日志的默认路径

1. 二进制日志(Binary Log) 在Linux系统中,二进制日志的默认路径通常为: /var/lib/mysql/hostname-bin.log 其中hostname是你的服务器主机名。如果没有特别配置,日志名可能是mysql-bin.log。 在Windows系统中&…

3.1k Star的特斯拉数据伴侣神器

微信公众号:[开源日记],分享10kStart的优质开源项目。 TeslaMate 适用于你的 Tesla 的功能强大的自托管数据记录器。 用 Elixir 编写数据存储在 Postgres 数据库使用 Grafana 进行可视化和数据分析车辆数据发布到本地 MQTT Broker GitHub数据 3.1k stars121 watching458 forks…

非关系型数据库Redis部署与常用命令

前言 Redis是一个高性能的开源内存数据库,常用于缓存、会话存储和实时数据处理,它是一款非关系型数据库。在生产环境中,Redis通过将数据存储在内存中以及支持多种数据结构,提供了快速的读写能力,并且可通过持久化功能…

龙晰系统运维相关笔记

一、硬盘分区、格式化及挂载(可直接查看另一篇文章硬盘分区格式化,或参考以下命令) #查看硬盘设备号fdisk -lfdisk /dev/vdb#以下为输入fdisk /dev/vdb命令后可以使用的命令行m #查看选项n #新建分区p 新建主分区1 新建1号分区2048 输入初始磁…

laravel如何通过DB获取一条数据的指定字段并转成数组

在 Laravel 中,如果你想要通过原生数据库查询构建器(DB facade)获取一条数据的指定字段,并将其转换为数组,你可以这样做: 首先,使用 select 方法来指定你想要获取的字段,然后使用 w…

L1-020 帅到没朋友分数 (20)

一、题目要求 当芸芸众生忙着在朋友圈中发照片的时候,总有一些人因为太帅而没有朋友。本题就要求你找出那些帅到没有朋友的人。 输入格式: 输入第一行给出一个正整数N(≤100),是已知朋友圈的个数;随后N行…

2023一个前端人的杂谈

酒香也怕巷子深 年底提车,回河北过年,一路总是旅游的牌子,后来去满城滑雪,随拍了几张照片,才更加感受河北的魅力。 感觉仅仅是这一抹黄昏,就让这一行物超所值了,原来那句宣传语所言非虚:这么近,那么美,周末到河北,然而我认为实际的好处,可能不止如此。 作为一个出…

记录一次hss不能防护主机的问题

场景:hss的控制台显示不在防护中,其他云主机并没有这个情况。 故障发生的时间是昨天下午15点半左右,运维同事做了重启网卡的操作。service network restart 排查分析: 于是仔细的查看日志,发现报错如下&#xff1a…

SpringBoot学习之Kibana下载安装和启动(Mac版)(三十二)

一、简介 Kibana是一个开源的分析与可视化平台,设计出来用于和Elasticsearch一起使用的。你可以用kibana搜索、查看存放在Elasticsearch中的数据。Kibana与Elasticsearch的交互方式是各种不同的图表、表格、地图等,直观的展示数据,从而达到高级的数据分析与可视化的目的。 …

ChatGPT与生成式AI:教育领域内新的浪潮与挑战

随着ChatGPT和其他生成式AI技术,如GPT-3.5、GPT-4的出现,我们正见证教育领域一场前所未有的变革浪潮。这些技术不仅推动了教育方式的进步,也为学习者带来了全新的机遇和挑战。 NO.1教育变革的新浪潮 生成式AI技术,特别是ChatGPT&…

FPGA(Verilog)实现按键消抖

实现按键消抖功能: 1.滤除按键按下时的噪声和松开时的噪声信号。 2.获取已消抖的按键按下的标志信号。 3.实现已消抖的按键的连续功能。 Verilog实现 模块端口 key_filter(input wire clk ,input wire rst_n ,input wire key_in , //按下按键时为0output …