一、多进程
1.1 进程的创建步骤
-
导入进程包
import multiprocessing
-
通过进程类创建进程对象
进程对象 = multiprocessing.Process() -
启动进程执行任务
进程对象.start()
1.2 通过进程类创建进程对象
进程对象 = multiprocessing.Process(target=任务名)
参数名 | 说明 |
---|---|
target | 执行的目标任务名,这里指的是函数名(方法名) |
name | 进程名,一般不用设置 |
group | 进程组,目前只能使用None |
1.3 进程创建与启动的代码
import multiprocessing
import time
def print1():
while True:
time.sleep(3)
print('11111')
def print2():
while True:
time.sleep(3)
print('22222')
if __name__ == '__main__':
sing_process1 = multiprocessing.Process(target=print1)
sing_process2 = multiprocessing.Process(target=print2)
sing_process1.start()
sing_process2.start()
1.4 进程执行带有参数的任务
参数名 | 说明 |
---|---|
args | 以元组的方式给执行任务传参 |
kwargs | 以字典方式给执行任务传参 |
1.5 args参数的使用
def print1(s):
while True:
time.sleep(3)
print(s)
if __name__ == '__main__':
# target: 进程执行的函数名
# args: 表示以元组的方式给函数传参
sing_process1 = multiprocessing.Process(target=print1, args=("哈哈哈哈", ))
sing_process1.start()
1.6 kwargs参数的使用
def print2(s):
while True:
time.sleep(3)
print(s)
if __name__ == '__main__':
# target: 进程执行的函数名
# args: 表示以元组的方式给函数传参
sing_process2 = multiprocessing.Process(target=print2, kwargs={"s": "我是进程2"})
sing_process2.start()
1.7、获取进程编号
进程编号的作用
当程序中进程的数量越来越多时,如果没有办法区分主进程和子进程还有不同的子进程,那么就无法进行有效的进程管理,为了方便管理实际上每个进程都是有自己编号的。
获取当前进程的编号和父进程的编号:
def work(s):
while True:
time.sleep(3)
# 当前进程的编号(os.getpid())
print("p1-id:", os.getpid())
# 父进程的编号 (os.getppid())
print("p1-pppp", os.getppid())
1.8 、进程的注意点主进程默认会等待所有的子进程执行结束再结束
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-lw6dVg2G-1641436802150)(D:\data\projects\gitPro\ZhuBlogHexo\source\images\questions\image-202106241321.png)]
想要主进程结束,子进程也跟着结束,需要设置守护主进程
import multiprocessing
import time
def work():
while True:
time.sleep(1)
print("子进程正在工作中")
if __name__ == '__main__':
m_work = multiprocessing.Process(target=work)
# 设置守护
m_work.daemon = True
m_work.start()
time.sleep(3)
print("主进程结束了")
1.9、多进程实现文件夹多任务白拷贝器
import multiprocessing
import os
import time
class Solution:
def __init__(self):
pass
def copy_file(self, source_path, target_path):
with open(source_path, "rb") as source_file:
with open(target_path, "wb") as target_source_file:
while True:
if data := source_file.read():
target_source_file.write(data)
else:
break
def main():
start_t = time.time()
source = "D:\\data\\【51优质资源 www.51data.org】算法训练营\\第0课"
target_source = "E:\\算法训练营"
source_list = os.listdir(source)
print(source_list)
try:
os.mkdir(target_source)
except:
print("文件夹已经存在")
for path in source_list:
m = multiprocessing.Process(Solution().copy_file(source + "\\" + path, target_source + "\\" + path))
m.start()
end_t = time.time()
print(end_t - start_t)
if __name__ == '__main__':
main()
二、多线程
线程介绍 :
- 多线程是Python程序中实现多任务的一种方式。
- 线程是程序执行的最小单位。
- 同属一个进程的多个线程**共享进程所拥有的全部资源 **
2.1 实现多任务的另一种形式
在Python中,想要实现多任务还可以使用多线程来完成
2.2 为什么使用多线程?
进程是分配资源的最小单位,一旦创建一个进程就会分配一定的资源,就像跟两个人聊QQ就需要打开两个QQ软件一样是比较浪费资源的。
线程是程序执行的最小单位,实际上进程只负责分配资源,而利用这些资源执行程序的线程,也就说进程是线程的窗口,一个进程中最少有一个线程来负责执行程序,同时线程自己不拥有系统资源,只需要一点儿在运行中必不可少的资源,但它可与同属一个进程的其它线程共享进程所拥有的全部资源,这就像通过一个QQ软件(一个进程)打开两个窗口(两个线程)跟两个人聊天一样,实现多任务的同时也节省了资源。
2.3 线程的创建步骤
2.3.1 导入线程模块
import threading
2.3.2 通过线程类创建线程对象
线程对象 = threading.Thread(target=任务名)
2.3.3 启动线程执行任务
线程对象.start()
2.4 通过线程类创建线程对象
线程对象=threading.Thread(target=任务名)
参数名 | 说明 |
---|---|
target | 执行的目标任务名,这里指的是函数名(方法名) |
name | 线程名,一般不用设置 |
group | 线程组,目前只使用None |
import threading
import time
def dance():
for _ in range(3):
print("跳舞")
time.sleep(1)
def sing():
for _ in range(3):
print("唱歌")
time.sleep(1)
if __name__ == '__main__':
t1 = threading.Thread(target=dance)
t2 = threading.Thread(target=sing)
t1.start()
t2.start()
2.5 线程执行带有参数的任务
参数名 | 说明 |
---|---|
args | 以元组的方式给执行任务传参 |
kwargs | 以字典方式给执行任务传参 |
1、args的使用
import threading
import time
def dance(n):
for _ in range(n):
print("跳舞")
time.sleep(1)
if __name__ == '__main__':
# target:线程执行的函数名
# args:表示以无组的方式给函数传参,逗号不能丢
t1 = threading.Thread(target=dance, args=(3, ))
2、kwargs的使用
import threading
import time
def dance(n):
for _ in range(n):
print("跳舞")
time.sleep(1)
if __name__ == '__main__':
# target:线程执行的函数名
# kwargs:表示以字典的方式给函数传参
t1 = threading.Thread(target=dance, kwargs={"n": 3})
2.6、主线程和子线程的结束顺序
- 主线程默认会等待所有子线程执行结束之后再结束 ,除非设置子线程守护主线程
- 设置守护主线程有两种方式:
- threading.Thread(target=work, daemon=True)
- 线程对象.setDaemon(True)
2.7、线程间的执行顺序
线程之间执行是无序的,是由CPU调度决定某个线程先执行的
2.8、多线程实现文件夹多任务白拷贝器
import multiprocessing
import os
import time
class Solution:
def __init__(self):
pass
def copy_file(self, source_path, target_path):
with open(source_path, "rb") as source_file:
with open(target_path, "wb") as target_source_file:
while True:
if data := source_file.read():
target_source_file.write(data)
else:
break
def main():
start_t = time.time()
source = "D:\\data\\【51优质资源 www.51data.org】算法训练营\\第0课"
target_source = "E:\\算法训练营"
source_list = os.listdir(source)
print(source_list)
try:
os.mkdir(target_source)
except:
print("文件夹已经存在")
for path in source_list:
m = multiprocessing.Process(Solution().copy_file(source + "\\" + path, target_source + "\\" + path))
m.start()
end_t = time.time()
print(end_t - start_t)
if __name__ == '__main__':
main()
2.9 获取线程id
threading.currentThread().ident
三、进程和线程对比
3.1、关系对比
(1)线程是依附在进程里面的,没有进程就没有线程。
(2)一个进程默认提供一条线程,进程可以创建多个线程。
3.2、区别对比
- 创建进程的资源开销要比创建线程的资源开销要大
- 进程是操作系统资源分配的基本单位,线程是CPU调度的基本单位
- 线程不能够独立执行,必须依存在进程中
3.3、优缺点对比
-
进程优缺点:
- 优点:可以用多核
- 缺点:资源开销大
-
线程优缺点:
- 优点:资源开销小
- 缺点:不能使用多核