多任务介绍
利⽤现学知识能够让两个函数或者⽅法同时执⾏吗?
不能,因为之前所写的程序都是单任务的,也就是说⼀个函数或者⽅法执⾏完成另外⼀个函数或者⽅法才能执⾏,要想实现这种操作就需要使⽤多任务。
多任务的最⼤好处是充分利⽤CPU资源,提⾼程序的执⾏效率。
多任务的定义
多任务是指在同⼀时间内执⾏多个任务,例如: 现在电脑安装的操作系统 都是多任务操作系统,可以同时运⾏着多个软件。
多任务的执行方式
并发
在⼀段时间内交替去执⾏任务。
对于单核cpu处理多任务,操作系统轮流让各个软件交替执⾏,假如:软件1 执⾏0.01秒,切换到软件2,软件2执⾏0.01秒,再切换到软件3,执⾏ 0.01秒……这样反复执⾏下去。表⾯上看,每个软件都是交替执⾏的,但 是,由于CPU的执⾏速度实在是太快了,我们感觉就像这些软件都在同时执⾏⼀样,这⾥需要注意单核cpu是并发的执⾏多任务的
并行
对于多核cpu处理多任务,操作系统会给cpu的每个内核安排⼀个执⾏的软件,多个内核是真正的⼀起执⾏软件。这⾥需要注意多核cpu是并⾏的执 ⾏多任务,始终有多个软件⼀起执⾏
多进程
在Python中,想要实现多任务可以使用多进程来完成。
进程的介绍
进程(Process)是资源分配的最小单位,它是操作系统进行资源分配和调度运行的基本单位,通俗理解:一个正在运行的程序就是一个进程 . 例如:正在运行的qq , 微信等 他们都是一个进程
一个程序运行后至少有一个进程 .
作用
图中是一个非常简单的程序 , 一旦运行hello.py这个程序 , 按照代码的执行顺序 , func_a函数执行完毕后才能执行func_b函数 . 如果可以让func_a和func_b同时运行 , 显然执行hello.py这个程序的效率会大大提升 .
多进程完成多任务
进程的创建步骤
- 导入进程包
import multiprocessing
- 通过进程类创建进程对象
进程对象 = multiprocessing.Process(target=任务名)
- 启动进程执行任务
进程对象.start()
通过进程类创建进程对象
代码演示:
# 导入进程模块
import multiprocessing
import time
# 编写代码
def coding():
for i in range(3):
print("coding...")
time.sleep(0.2)
# 听音乐
def music():
for i in range(3):
print("music...")
time.sleep(0.2)
if __name__ == '__main__':
# coding()
# music()
# 通过进程类创建进程对象
coding_process = multiprocessing.Process(target=coding)
# 通过进程类创建进程对象
music_process = multiprocessing.Process(target=music)
# 启动进程
coding_process.start()
music_process.start()
进程执行带有参数的任务
代码演示:
# 导入进程模块
import multiprocessing
import time
# 编写代码
def coding(num, name):
for i in range(num):
print(name)
print("coding...")
time.sleep(0.2)
# 听音乐
def music(count):
for i in range(count):
print("music...")
time.sleep(0.2)
if __name__ == '__main__':
# coding()
# music()
# 通过进程类创建进程对象
coding_process = multiprocessing.Process(target=coding, args=(3, "传智"))
# 通过进程类创建进程对象
music_process = multiprocessing.Process(target=music, kwargs={"count": 2})
# 启动进程
coding_process.start()
music_process.start()
进程执行带有参数的任务传参有两种方式:
元组方式传参
:元组方式传参一定要和参数的顺序保持一致。
字典方式传参
:字典方式传参字典中的key一定要和参数名保持一致。
获取进程编号
进程编号的作用
:
当程序中进程的数量越来越多时 , 如果没有办法区分主进程和子进程还有不同的子进程 , 那么就无法进行有效的进程管理 , 为了方便管理实际上每个进程都是有自己编号的 .
获取进程编号的两种方式
:
- 获取当前进程编号
- 获取当前父进程编号
os.getpid()的使用
import os
pid = os.getpid()
print(pid)
# 或者
import multiprocessing
pid = multiprocessing.current_process().pid
print(pid)
os.getppid()的使用
def work():
# 查看当前进程
current_process = multiprocessing.current_process()
# 获取当前进程的编号
print(“work进程编号:”, current_process.pid, os.getpid())
# 获取父进程的编号
print(“work父进程的编号:”, os.getppid())
os.kill()的使用
def work():
# 查看当前进程
current_process = multiprocessing.current_process()
# 获取当前进程的编号
print(“work进程编号:”, current_process.pid, os.getpid())
# 获取父进程的编号
print(“work父进程的编号:”, os.getppid())
for i in range(10):
print(“工作中....”)
time.sleep(0.2)
# 根据进程编号杀死对应的进程
os.kill(os.getpid(), 9)
代码展示:
# 导入进程模块
import multiprocessing
import time
import os
# 编写代码
def coding():
print("coding>>>%d" % os.getpid())
for i in range(3):
print("coding...")
time.sleep(0.2)
# 听音乐
def music():
for i in range(3):
print("music...")
time.sleep(0.2)
if __name__ == '__main__':
# coding()
# music()
# 通过进程类创建进程对象
coding_process = multiprocessing.Process(target=coding)
# 通过进程类创建进程对象
music_process = multiprocessing.Process(target=music)
# 启动进程
coding_process.start()
music_process.start()
进程间不共享全局变量
进程间是不同享全局变量的.
实际上创建一个紫禁城就是把主进程的资源进行拷贝产生了一个新的进程,这里主进程和子进程是相互独立的.
import multiprocessing
import time
# 全局变量
my_list = []
# 写入数据
def write_data():
for i in range(3):
my_list.append(i)
print("add:", i)
print("write_data", 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()
主进程与子进程的结束顺序
主进程和子进程的结束顺序
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()
# 延时1秒
time.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()
# 延时1秒
time.sleep(1)
# 手动结束子进程
work_process.terminate()
print("主进程执行完毕")
为了保证子进程能够正常的运行,主进程会等所有的子进程执行完成以后再销毁,设置守护主进程的目的是主进程退出子进程销毁,不让主进程再等待子进程去执行。
设置守护主进程方式:
子进程对象.daemon = True
销毁子进程方式:
子进程对象.terminate()
提示: 以上两种方式都能保证主进程退出子进程销毁