Python基础语法文章导航:
- Python基础(01初识数据类型&变量)
- Python基础(02条件&循环语句)
- Python基础(03字符串格式化&运算符&进制&编码)
- Python基础(04 基础练习题)
- Python数据类型(day05整型&布尔类型&字符串类型)
- Python数据类型(06列表&元组)
- Python数据类型(07集合&字典&浮点型&None)
- Python文件操作01(自动化测试文件相关操作)
-
Python函数入门(08函数定义&参数&返回值)
-
Python文件操作02(自动化测试文件相关操作)
-
Python函数(10生成器&内置函数&推导式)
-
Python函数(11自定义模块&第三方模块&内置模块)
-
Python函数(12时间处理&正则表达式)
-
Python函数(13面向对象)
-
Python面向对象(15成员&成员修饰符)
目录
一.了解进程和线程
二.多线程
三.多进程
四.GIL锁
一.了解进程和线程
先来了解下进程和线程。
类比:
-
一个工厂,至少有一个车间,一个车间中至少有一个工人,最终是工人在工作。
-
一个程序,至少有一个进程,一个进程中至少有一个线程,最终是线程在工作。
线程,是计算机中可以被cpu调度的最小单元(真正在工作)。
进程,是计算机资源分配的最小单元(进程为线程提供资源)。一个进程中可以有多个线程,同一个进程中的线程可以共享此进程中的资源。
二.多线程
基于多线程对上述串行示例进行优化:
-
一个工厂,创建一个车间,这个车间中创建 3个工人,并行处理任务。
-
一个程序,创建一个进程,这个进程中创建 3个线程,并行处理任务。
import time
import requestsurl_list = [("东北F4模仿秀.mp4", "https://aweme.snssdk.com/aweme/v1/playwm/?video_id=v0300f570000bvbmace0gvch7lo53oog"),("卡特扣篮.mp4", "https://aweme.snssdk.com/aweme/v1/playwm/?video_id=v0200f3e0000bv52fpn5t6p007e34q1g"),("罗斯mvp.mp4", "https://aweme.snssdk.com/aweme/v1/playwm/?video_id=v0200f240000buuer5aa4tij4gv6ajqg")
]for file_name, url in url_list:res = requests.get(url)with open(file_name, mode='wb') as f:f.write(res.content)
import time
import requests
import threading
"""
def func(a1,a2,a3):passt = threaing.Thread(target=func,args=(11,22,33))
t.start()
"""url_list = [("东北F4模仿秀.mp4", "https://aweme.snssdk.com/aweme/v1/playwm/?video_id=v0300f570000bvbmace0gvch7lo53oog"),("卡特扣篮.mp4", "https://aweme.snssdk.com/aweme/v1/playwm/?video_id=v0200f3e0000bv52fpn5t6p007e34q1g"),("罗斯mvp.mp4", "https://aweme.snssdk.com/aweme/v1/playwm/?video_id=v0200f240000buuer5aa4tij4gv6ajqg")
]def task(file_name, video_url):res = requests.get(video_url)with open(file_name, mode='wb') as f:f.write(res.content)print(time.time())for name, url in url_list:# 创建线程,让每个线程都去执行task函数(参数不同)t = threading.Thread(target=task, args=(name, url))t.start()
三.多进程
基于多进程对上述串行示例进行优化:
-
一个工厂,创建 三个车间,每个车间 一个工人(共3人),并行处理任务。
-
一个程序,创建 三个进程,每个进程 一个线程(共3人),并行处理任务。
import time
import requests
import multiprocessing# 进程创建之后,在进程中还会创建一个线程。
# t = multiprocessing.Process(target=函数名, args=(name, url))
# t.start()url_list = [("东北F4模仿秀.mp4", "https://aweme.snssdk.com/aweme/v1/playwm/?video_id=v0300f570000bvbmace0gvch7lo53oog"),("卡特扣篮.mp4", "https://aweme.snssdk.com/aweme/v1/playwm/?video_id=v0200f3e0000bv52fpn5t6p007e34q1g"),("罗斯mvp.mp4", "https://aweme.snssdk.com/aweme/v1/playwm/?video_id=v0200f240000buuer5aa4tij4gv6ajqg")
]def task(file_name, video_url):res = requests.get(video_url)with open(file_name, mode='wb') as f:f.write(res.content)print(time.time())if __name__ == '__main__':print(time.time())for name, url in url_list:t = multiprocessing.Process(target=task, args=(name, url))t.start()
四.GIL锁
GIL, 全局解释器锁(Global Interpreter Lock),是CPython解释器特有一个玩意,让一个进程中同一个时刻只能有一个线程可以被CPU调用。
如果程序想利用 计算机的多核优势,让CPU同时处理一些任务,适合用多进程开发(即使资源开销大)。
如果程序不利用 计算机的多核优势,适合用多线程开发。
常见的程序开发中,计算操作需要使用CPU多核优势,IO操作不需要利用CPU的多核优势,所以,就有这一句话:
-
计算密集型,用多进程,例如:大量的数据计算【累加计算示例】。
-
IO密集型,用多线程,例如:文件读写、网络数据传输【下载抖音视频示例】。
累加计算示例(计算密集型):
-
串行处理
import timestart = time.time()result = 0
for i in range(100000000):result += i
print(result)end = time.time()print("耗时:", end - start) # 耗时: 9.522780179977417
多进程处理
import time
import multiprocessingdef task(start, end, queue):result = 0for i in range(start, end):result += iqueue.put(result)if __name__ == '__main__':queue = multiprocessing.Queue()start_time = time.time()p1 = multiprocessing.Process(target=task, args=(0, 50000000, queue))p1.start()p2 = multiprocessing.Process(target=task, args=(50000000, 100000000, queue))p2.start()v1 = queue.get(block=True) #阻塞v2 = queue.get(block=True) #阻塞print(v1 + v2)end_time = time.time()print("耗时:", end_time - start_time) # 耗时: 2.6232550144195557
当然,在程序开发中 多线程 和 多进程 是可以结合使用,例如:创建2个进程(建议与CPU个数相同),每个进程中创建3个线程。
import multiprocessing
import threadingdef thread_task():passdef task(start, end):t1 = threading.Thread(target=thread_task)t1.start()t2 = threading.Thread(target=thread_task)t2.start()t3 = threading.Thread(target=thread_task)t3.start()if __name__ == '__main__':p1 = multiprocessing.Process(target=task, args=(0, 50000000))p1.start()p2 = multiprocessing.Process(target=task, args=(50000000, 100000000))p2.start()