第十六章---多线程和多进程
目录:
(一)多任务介绍
1.1概念
1.2多任务的两种表现形式
(二)进程
2.1进程的概念
2.2多进程的作用
2.3进程的创建步骤
2.4单任务和多任务简单例子
2.5 进程执行带有参数的任务
2.6获取进程编号
2.7进程的注意点
2.8案例-多进程实现视频文件夹多任务拷贝器
(三)线程
3.1线程的介绍
3.2线程的创建步骤
3.3通过线程类创建线程对象
3.4线程执行带有参数的任务
3.5线程的例子
3.6主线程与子线程的结束顺序
3.7线程之间的执行顺序
3.8多线程项目
(四)线程与进程的对比
4.1关系对比
4.2区别对此
4.3优缺点对比
正文:
(一)多任务介绍
1.1概念
多任务是指在同一时间内执行多个任务。如操作系统!
1.2多任务的两种表现形式
并发(在一段时间内交替去执行多个任务)
cpu隔几秒切换任务一二三。
并行(在一段时间内真正的同时一起执行多个任务)
(二)进程
2.1进程的概念:
进程是资源分配的最小单位,他是操作系统进行资源分配和调度运行的基本单位。通俗理解:一个正在运行的一个程序就是一个进程。例如:正在运行的qq、wechat等,它们都是一个进程。
2.2多进程的作用
2.3进程的创建步骤
-
导入进程包
import multiprocessing
-
通过进程类创建进程对象
进程对象 = multiprocessing.Process()
-
启动进程执行任务
进程对象.start()
通过进程类创建进程对象
2.4单任务和多任务简单例子
-
单任务
import time def sing(): for i in range(3): print("唱歌。。。") time.sleep(0.5) def dance(): for i in range(3): print("跳舞。。。") time.sleep(0.5) if __name__ == '__main__': time1 = time.time() sing() dance() print(time.time()-time1)
输出结果
唱歌。。。
唱歌。。。
唱歌。。。
跳舞。。。
跳舞。。。
跳舞。。。
3.0027265548706055
使用多进程实现多任务
import multiprocessing import time def sing(): for i in range(3): print("唱歌。。。") time.sleep(0.5) def dance(): for i in range(3): print("跳舞。。。") time.sleep(0.5) if __name__ == '__main__': time1 = time.time() s1 = multiprocessing.Process(target=sing) d1 = multiprocessing.Process(target=dance) s1.start() d1.start() s1.join() #这个方法可以等待子进程结束后再继续往下运行,通常用于进程间的同步 d1.join() print(time.time()-time1)
输出结果
唱歌。。。
跳舞。。。
唱歌。。。
跳舞。。。
唱歌。。。
跳舞。。。
1.7515902519226074
2.5 进程执行带有参数的任务
import multiprocessing import time def sing(name, num): for i in range(num): print("%s在唱歌。。。"%name) time.sleep(0.5) def dance(num): for i in range(num): print("跳舞。。。") time.sleep(0.5) if __name__ == '__main__': # 以元组形式传参 s1 = multiprocessing.Process(target=sing, args=('小明', 3)) # 以字典形式传参 d1 = multiprocessing.Process(target=dance, kwargs={"num": 5, }) s1.start() d1.start()
注意事项
元组传参一定要和参数顺序一致
字典方式传参时字典的key要和参数名一致
2.6获取进程编号
进程编号的作用:
当程序中进程的数量越来越多时,如果没有办法区分主进程和子进程还有不同的子进程,那么就无法进行有效的进程管理,为了方便管理实际上每个进程都是有自己的编号的。
获取进程编号的两种方式:
-
获取当前进程编号
os.getpid()
-
获取当前父进程编号
os.getppid()
import multiprocessing import time import os def sing(name, num): print("唱歌进程的编号: ", os.getpid()) print("唱歌进程的父进程的编号: ", os.getppid()) for i in range(num): print("%s在唱歌。。。"%name) time.sleep(0.5) def dance(num): print("跳舞进程的编号: ", os.getpid()) print("跳舞进程的父进程的编号: ", os.getppid()) for i in range(num): print("跳舞。。。") time.sleep(0.5) if __name__ == '__main__': print("主进程的编号: ", os.getpid()) # 以元组形式传参 顺序和参数顺序一致 s1 = multiprocessing.Process(target=sing, args=('小明', 3)) # 以字典形式传参 key和参数名保持一致 d1 = multiprocessing.Process(target=dance, kwargs={"num": 5, }) s1.start() d1.start()
输出结果: 主进程的编号: 10620 唱歌进程的编号: 18412 唱歌进程的父进程的编号: 10620 小明在唱歌。。。 跳舞进程的编号: 9924 跳舞进程的父进程的编号: 10620 跳舞。。。 小明在唱歌。。。 跳舞。。。 小明在唱歌。。。 跳舞。。。 跳舞。。。 跳舞。。。
2.7进程的注意点
-
主进程会等待所有的子进程执行结束在结束
是否像上面所说的那样?
import time import multiprocessing def work(): for i in range(10): print("工作中。。。。") time.sleep(0.2) if __name__ == '__main__': work_process = multiprocessing.Process(target=work) work_process.start() time.sleep(1) print("主进程执行结束")
输出结果:
工作中。。。。
工作中。。。。
工作中。。。。
工作中。。。。
主进程执行结束
工作中。。。。
工作中。。。。
工作中。。。。
工作中。。。。
工作中。。。。
工作中。。。。
实际上不是,怎么办呢?能QQ一样,关闭主进程,子进程也跟着结束?设置子进程守护主进程
· 设置守护主进程
主进程结束后不会再继续执行子进程中剩余的工作
import time import multiprocessing def work(): for i in range(10): print("工作中。。。。") time.sleep(0.2) if __name__ == '__main__': # 设置守护主进程,主进程执行完成,则结束 # 方式1 work_process = multiprocessing.Process(target=work, daemon=True) # 方式2 # work_process.daemon = True work_process.start() time.sleep(1) print("主进程执行结束")
输出结果:
工作中。。。。
工作中。。。。
工作中。。。。
工作中。。。。
主进程执行结束
2.8案例-多进程实现视频文件夹多任务拷贝器
- 需求分析:
- 目标文件夹是否存在,如果不存在就创建,存在则不创建
- 遍历源文件夹中所有文件,并拷贝到目标文件夹
- 采用进程实现多任务,并完成拷贝
- 实现步骤
- 定义源文件夹所在的路径,目标文件夹所在路径
- 创建目标文件夹
- 通过
os.listdir
获取源目录中的文件列表 - 遍历每个文件,定义一个函数,专门实现文件拷贝
- 采用进程实现多任务,完成高并发拷贝
import os import multiprocessing def copy_file(file_name, source_dir, dest_dir): # 1 拼接源文件路径和目标文件路径 source_path = source_dir + '\\' + file_name dest_path = dest_dir + '\\' + file_name # 2 打开源文件和目标文件 with open(source_path, 'rb') as source_file: with open(dest_path, 'wb') as dest_file: # 3 循环读取源文件到目标路径 while True: data = source_file.read(1024) if data: dest_file.write(data) else: break if __name__ == '__main__': # 1 定义源文件夹和目标文件夹 source_dir = r'F:\迅雷下载\视频-智能机器人从0到1系统入门课程\视频' dest_dir= r'F:\目标文件夹' # 2.创建目标文件夹 try: os.mkdir(dest_dir) except: print("目标文件夹已经存在") # 3.读取源文件夹的文件列表 file_list = os.listdir(source_dir) # 4.遍历文件列表实现拷贝 for file_name in file_list: # copy_file(file_name, source_dir, dest_dir) # 5.使用多进程实现多任务拷贝 sub_process = multiprocessing.Process(target=copy_file, args=(file_name, source_dir, dest_dir)) sub_process.start()
(三)线程
3.1线程的介绍
- 实现多任务的另一种形式
- 线程是程序执行的最小单位
- 同属一个进程的多个线程共享进程所拥有的全部资源
为什么需要线程?
多线程的作用?
3.2线程的创建步骤
-
导入线程包
import threading
-
通过线程类创建线程对象
线程对象 = threading.Thread(target=任务名)
-
启动线程执行任务
线程对象.start()
3.3通过线程类创建线程对象
3.4线程执行带有参数的任务
3.5线程的例子
这个需要6秒
只需要三秒
import os import threading def copy_file(file_name, source_dir, dest_dir): # 1 拼接源文件路径和目标文件路径 source_path = source_dir + '\\' + file_name dest_path = dest_dir + '\\' + file_name # 2 打开源文件和目标文件 with open(source_path, 'rb') as source_file: with open(dest_path, 'wb') as dest_file: # 3 循环读取源文件到目标路径 while True: data = source_file.read(1024) if data: dest_file.write(data) else: break if __name__ == '__main__': # 1 定义源文件夹和目标文件夹 source_dir = r'F:\迅雷下载\视频-智能机器人从0到1系统入门课程\视频' dest_dir= r'F:\目标文件夹' # 2.创建目标文件夹 try: os.mkdir(dest_dir) except: print("目标文件夹已经存在") # 3.读取源文件夹的文件列表 file_list = os.listdir(source_dir) # 4.遍历文件列表实现拷贝 for file_name in file_list: # copy_file(file_name, source_dir, dest_dir) # 5.使用多线程实现多任务拷贝 sub_thread = threading.Thread(target=copy_file, args=(file_name, source_dir, dest_dir)) sub_thread.start()
3.6主线程与子线程的结束顺序
结论:主线程会等待所有子线程的结束而结束。如果我们想主线程结束后,子线程会自动销毁,怎么做尼?
有,可以设置守护主线程,如下:
3.7线程之间的执行顺序
无序,由CPU调度决定某个线程先执行
3.8多线程项目
import os import threading def copy_file(file_name, source_dir, dest_dir): # 1 拼接源文件路径和目标文件路径 source_path = source_dir + '\\' + file_name dest_path = dest_dir + '\\' + file_name # 2 打开源文件和目标文件 with open(source_path, 'rb') as source_file: with open(dest_path, 'wb') as dest_file: # 3 循环读取源文件到目标路径 while True: data = source_file.read(1024) if data: dest_file.write(data) else: break if __name__ == '__main__': # 1 定义源文件夹和目标文件夹 source_dir = r'F:\迅雷下载\视频-智能机器人从0到1系统入门课程\视频' dest_dir= r'F:\目标文件夹' # 2.创建目标文件夹 try: os.mkdir(dest_dir) except: print("目标文件夹已经存在") # 3.读取源文件夹的文件列表 file_list = os.listdir(source_dir) # 4.遍历文件列表实现拷贝 for file_name in file_list: # copy_file(file_name, source_dir, dest_dir) # 5.使用多线程实现多任务拷贝 sub_thread = threading.Thread(target=copy_file, args=(file_name, source_dir, dest_dir)) sub_thread.start()
(四)线程与进程的对比
4.1关系对比
- 线程是依附在进程里面的,没有线程就没有进程
- 一个进程默认提供一条线程,进程可以创建多个线程
4.2区别对此
- 创建进程的资源开销要比创建线程的资源开销要大
- 进程是操作系统资源分配的基本单位,线程是CPU调度的基本单位
- 线程不能够独立执行,必须依存在进程中
4.3优缺点对比
- 进程优缺点:
- 优点:可以用多核
- 缺点:资源开销大
- 线程优缺点:
- 优点:资源开销小
- 缺点:不可用多核
参考:
https://blog.csdn.net/princezf/article/details/113110550