目录
python多任务
使用多任务的作用在于充分利用CPU资源,提高程序执行的效率,通常有并发和并行两种形式
实现方式:
-
多进程
-
多线程
多进程
进程概念
进程(Process)是资源分配的最小单位,它是操作系统进行资源分配和调度运行的基本单位,通俗理解:一个正在运行的程序就是一个进程﹒例如:正在运行的QQ,微信等他们都是一个进程.(而没有运行的称为程序)
如图,CPU会为进程分配内存、磁盘、网络等等资源
注:一个运行起来的程序至少有一个进程,也可以有多个
多进程作用
比如,程序中有两个函数AB, 多进程可以实现AB两个函数同时运行,这样就提高了效率。
程序运行中会产生一个主进程,若创建一个子进程,二者同时运行就实现了多进程。
进程的创建
1、 导入进程包
import multiprocessing
2、创建进程对象
进程对象=multiprocessing.Process(target=任务名)
参数还有 name:进程名,一般不用设置 group: 进程组,只能用None
3、启动进程执行任务
进程对象.start()
示例代码01
import multiprocessing
import time
def sing():
for i in range(2):
print('唱歌')
time.sleep(0.5)
def dance():
for i in range(2):
print('跳舞')
time.sleep(0.5)
if __name__=='__main__':
sing_process=multiprocessing.Process(target=sing)
dance_process=multiprocessing.Process(target=dance)
sing_process.start()
dance_process.start()
-----------------------------------------------------------------------------------------
结果:
唱歌
跳舞
唱歌
跳舞
进程执行带有参数的任务
方式:
(需要注意的是,元组传参里面必须跟逗号)
(字典的键必须和参数名一样,键对应的值就是传入的参数值)
示例代码02
import multiprocessing
import time
def sing(num):
for i in range(num,name): #num形参 name形参
print(name)
print('唱歌')
time.sleep(0.5)
def dance(num):
for i in range(num,name): #num形参 name形参
print(name)
print('跳舞')
time.sleep(0.5)
if __name__=='__main__':
sing_process=multiprocessing.Process(target=sing,args=(3,'小明'))
#元组方式传参,按顺序
dance_process=multiprocessing.Process(target=dance,kwargs={'name':'小红','num':2})
#字典方式传参,可不按顺序,键名匹配即可
sing_process.start()
dance_process.start()
-----------------------------------------------------------------------------------------
结果:
小明
唱歌
小红
跳舞
小明
唱歌
小红
跳舞
获取进程编号
进程编号的作用:
当程序中进程的数量越来越多时,如果没有办法区分主进程和子进程还有不同的子进程,那么就无法进行有效的进程管理,为了方便管理实际上每个进程都是有自己编号的.
获取进程编号的方式:
-
获取当前进程编号
os.getpid()
-
获取当前父进程的编号
os.getppid()
示例代码03
import os
import multiprocessing
import time
def sing(num):
print('唱歌进程编号:',os.getpid()) #获得当前唱歌进程的编号
print('唱歌进程的父进程编号(即主进程):',os.getppid()) #获得唱歌进程的父进程的编号
for i in range(num,name): #num形参 name形参
print(name)
print('唱歌')
time.sleep(0.5)
def dance(num):
for i in range(num,name): #num形参 name形参
print(name)
print('跳舞')
time.sleep(0.5)
if __name__=='__main__':
print('主进程编号:',os.getpid()) #获得主进程的编号,发现和唱歌进程的父进程编号一致
sing_process=multiprocessing.Process(target=sing,args=(3,'小明'))
#元组方式传参,按顺序
dance_process=multiprocessing.Process(target=dance,kwargs={'name':'小红','num':2})
#字典方式传参,可不按顺序,键名匹配即可
sing_process.start()
dance_process.start()
-----------------------------------------------------------------------------------------
结果:(省略部分)
主进程编号:79412
唱歌进程编号:79414
唱歌进程的父进程编号(即主进程):79412
设置守护主进程
线程和进程的对比
-
主进程会等待所有的子进程执行结束再结束
-
设置守护主进程
(主进程退出后子进程直接销毁,不再执行未完成的子进程代码,如QQ退出聊天框也会结束)
方式:
子进程对象.daemon=True
import time import multiprocessing def work(): for i in range(10): print('工作中') time.sleep(0.2) #那么此进程共执行2秒 if __name__=='__main__': work_process=multiprocessing.Process(target=work) work_process.daemon=True #!!!!!!!在这里设置daemon为True就完事了!!!!!!!!! work_process.start() time.sleep(1) #意思是主进程只执行1秒,那就比work的子进程短1秒 print('主进程执行完成!') -------------------------------------------------------------------------------------- 工作中 工作中 工作中 工作中 工作中 主进程执行完成! # 显然,子进程本来该有10次,这里未完成
多线程
线程概念
多线程是python实现多任务的一种方式,是程序执行的最小单位,同属一个进程的多个线程共享进程所拥有的全部资源
线程的创建步骤
1、 导入线程模块
import threading
2、创建线程对象
线程对象=threading.Thread(target=任务名) 参数还有 name:进程名,一般不用设置 group: 进程组,只能用None
3、启动线程执行任务
线程对象.start()
示例代码04
import threading def sing(): for i in range(2): print('唱歌') time.sleep(0.5) def dance(): for i in range(2): print('跳舞') time.sleep(0.5) if __name__=='__main__': sing_thread=threading.Thread(target=sing) dance_thread=threading.Thread(target=dance) sing_thread.start() dance_thread.start() ----------------------------------------------------------------------------------------- 唱歌 #实际上,唱歌和跳舞是同时打出的,那么只需要三次就执行完毕了 跳舞 唱歌 跳舞 唱歌 跳舞
线程执行有参数的任务
方式:
他们的使用方式和进程是一样的
示例代码05
import threadingthreading import time def sing(num): for i in range(num,name): #num形参 name形参 print(name) print('唱歌') time.sleep(0.5) def dance(num): for i in range(num,name): #num形参 name形参 print(name) print('跳舞') time.sleep(0.5) if __name__=='__main__': sing_process=threading.Process(target=sing,args=(3,'小明')) #元组方式传参,按顺序 dance_process=threading.Process(target=dance,kwargs={'name':'小红','num':2}) #字典方式传参,可不按顺序,键名匹配即可 sing_process.start() dance_process.start() ----------------------------------------------------------------------------------------- 结果: 小明 唱歌 小红 跳舞 小明 唱歌 小红 跳舞
主线程和子线程的结束顺序
和进程类似,主线程会在所有的子线程结束后再结束,同样的,我们也可以设置守护主线程
方法1
#在创建线程对象的时候, 指定daemon=True sing_process=threading.Process(target=sing,args=(3,'小明'),daemon=True)
方法2
#使用函数设置 sing_process.setDaemon(True)
线程之间的执行顺序
-
线程之间的执行是无序的,由CPU调度某个线程执行
-
获取当前的线程信息
#通过current_thread方法获取线程对象 current=threading.current_thread() #通过current对象可知线程的相关信息,例如被创建的顺序、名称 print(current)
-
关系对比
1.线程是依附在进程里面的,没有进程就没有线程。
2.一个进程默认提供一条线程,进程可以创建多个线程。
-
区别对比
1.创建进程的资源开销要比创建线程的资源开销要大
2.进程是操作系统资源分配的基本单位,线程是CPU调度的基本单位
3.线程不能独立执行,必须依附于进程
(进程注重资源分配,线程注重CPU调度)
-
优缺点对比
1.进程优缺点:
优点:可以用多核
缺点:资源开销大
2.线程优缺点:
优点:资源开销小
缺点:不能使用多核