多任务
- 多任务:一个时间内,执行多个任务
- 多任务的执行方式:
- 并发:多个任务交替执行(单核 CPU 一定是并发)
- 并行:在多核CPU中,多个任务在多个CPU上执行
[!tip|style:flat|label:提示]
一般来说,并发和并行是同时存在的,是操作系统自动调度
- 多任务的实现方式(如何写代码编程实现)
- 多进程实现
- 多线程实现
- 协成实现
- 时间片:操作系统分配给程序的一小段CPU时间
进程
进程的介绍
在Python程序中,想要实现多任务可以使用进程来完成,进程是实现多任务的一种方式。
进程的概念
一个正在运行的程序或者软件就是一个进程,它是
操作系统进行资源分配的基本单位,也就是说每启动一个进程,操作系统都会给其分配一定的运行资源(内存资源)保证进程的运行比如:现实生活中的公司可以理解成是一个进程,公司提供办公资源(电脑、办公桌椅等),真正干活的是员工,员工可以理解成线程。
[!tip|style:flat|label:提示]
一个程序运行后至少有一个进程,一个进程默认有一个线程,进程里面可以创建多个线程,线程是依附在进程里面的,没有进程就没有线程。进程的作用
[!tip|style:flat|label:提示]
多进程可以完成多任务,每个进程就好比一家独立的公司,每个公司都各自在运营,每个进程也各自在运行,执行各自的任务。
进程的概念
- 概念:
- 程序:安装的程序(QQ,LOL...),写的代码
- 进程:运行起来的程序就是进程
- 线程:一个进程中默认会有一个线程,线程是真正执行任务的
多进程的使用
# 导入进程包
import multiprocessing
# Process进程类说明
# Process([group [, target [,name [, args [, kwargs]]]]])
# group: 指定进程组,目前只能使用None
# target:执行的目标任务名
# name:进程名字
# args:以元组方式执行任务传参
# kwargs:以字典方式执行任务传参
# Process创建的实例对象的常用方法
# start():启动子进程实例(创建子进程)
# join():等待子进程执行结束
# terminate():不管任务是否完成,立即终止子进程
# Process创建的实例对象的常用属性
# name:当前的进程的别名。默认Process-N,N为从1开始递增的整数
# 导包
import multiprocessing
import time
def sing():
for i in range(5):
print('正在唱歌中....')
time.sleep(0.1) # 让进程手动失去CPU资源 让进程休眠0.1秒,今日阻塞态,失去cpu
def dance():
for i in range(5):
print('正在跳舞中.....')
time.sleep(0.1)
if __name__ == '__main__':
# sing()
# dance()
# 创建进程执行的任务,multiprocessing.Process(任务函数名)
# target 指定执行进程的任务,即函数名字,不能加括号,加括号代表着函数调用,会将函数的返回值返回给target
process_sing = multiprocessing.Process(target=sing)
process_dance = multiprocessing.Process(target=dance)
# 启动进程对象 进程对象.start()
process_sing.start()
process_dance.start()
获取进程编号
# 导包
import multiprocessing
import os
import time
def sing(): # 函数定义,主进程执行
print('sing', multiprocessing.current_process().name, os.getpid(), os.getppid())
for i in range(5):
print('正在唱歌中....')
time.sleep(0.1) # 让进程手动失去CPU资源 让进程休眠0.1秒,今日阻塞态,失去cpu
def dance(): # 函数定义,主进程执行
print('dance', multiprocessing.current_process().name, os.getpid(), os.getppid())
for i in range(5):
print('正在跳舞中.....')
time.sleep(0.1)
# os.kill(进程的id, 9) 杀死进程
# os.kill(os.getpid(), 9)
# 第二种写法
os.kill(multiprocessing.current_process().pid, 9)
if __name__ == '__main__':
# .name, os.getpid(), os.getppid() 获取名字 和进程的id
print('main', multiprocessing.current_process().name, os.getpid(), os.getppid())
# 创建进程执行的任务,即函数名字,不能加括号,加括号代表函数调用,会将返回函数值给target
process_sing = multiprocessing.Process(target=sing, name='sing') # 主进程创建子进程 name是修改进程名字
process_dance = multiprocessing.Process(target=dance) # 主进程创建子进程
process_sing.start()
process_dance.start()
进程的传参
# 导包
import multiprocessing
import os
import time
def sing(singer, song): # 函数定义,主进程执行
print('sing', multiprocessing.current_process().name, os.getpid(), os.getppid())
for i in range(5):
print(f'{singer}正在唱歌{song}中....')
time.sleep(0.1) # 让进程手动失去CPU资源 让进程休眠0.1秒,今日阻塞态,失去cpu
def dance(dancer, name): # 函数定义,主进程执行
print('dance', multiprocessing.current_process().name, os.getpid(), os.getppid())
for i in range(5):
print(f'{dancer}正在跳{name}舞.....')
time.sleep(0.1)
# os.kill(进程的id, 9) 杀死进程
# os.kill(os.getpid(), 9)
# 第二种写法
os.kill(multiprocessing.current_process().pid, 9)
if __name__ == '__main__':
# .name, os.getpid(), os.getppid() 获取名字 和进程的id
print('main', multiprocessing.current_process().name, os.getpid(), os.getppid())
# 创建进程执行的任务,即函数名字,不能加括号,加括号代表函数调用,会将返回函数值给target
# 进程传参,args 传参 实参是元组 kwargs 传参 实参是字典
process_sing = multiprocessing.Process(target=sing, name='sing', args=('刘德华', '忘情水')) # 主进程创建子进程 name是修改进程名字
process_dance = multiprocessing.Process(target=dance, kwargs={'dancer': '邓丽君', 'name': '万水千山总是情'}) # 主进程创建子进程
process_sing.start()
process_dance.start()
进程不共享全局变量
# 导包
import multiprocessing
import time
# 定义全局变量
g_list = []
# 定义任务函数,添加数据,修改变量的值
def add_data():
for i in range(5):
g_list.append(i)
print('添加数据', i)
time.sleep(0.1)
# 代码出了 for 循环,代表数据添加完成
print('add_data', g_list)
# 定义任务函数,都取全局变量的值
def read():
print('read:', g_list)
if __name__ == '__main__':
# 创建进程对象
process_add = multiprocessing.Process(target=add_data)
process_read = multiprocessing.Process(target=read)
# 启动进程
process_add.start()
# 进程对象.join() 阻塞等待进程完成
# 谁阻塞等待?代码书写在哪个进程,那个进程阻塞等待
# 阻塞等待谁执行完成? 那个进程对象.join()就是等待那个进程执行完成
process_add.join() # 主进程阻塞等待 2. 等待add进程执行完成
process_read.start()
主进程会等待子进程执行结束才结束
# 导包
import multiprocessing
import time
# 定义进程所需要执行的任务
def task():
for i in range(10):
print('任务执行中...')
time.sleep(0.5)
print('子进程代码结束')
if __name__ == '__main__':
sub_process = multiprocessing.Process(target=task)
# 方案二,进程设置为 daemon 进程
sub_process.daemon = True
sub_process.start()
time.sleep(1)
print('主进程的代码结束,理论上程序应该结束')
# 方案一:进程对象.terminate() 终止进程的执行
# sub_process.terminate()