目录
本篇仅展示代码,详细多线程教学移步(python爬虫之多线程)
多线程以及线程池:
from concurrent.futures import ThreadPoolExecutor
def work():
res = 0
for i in range(100000000):
res += i
def main_thread():
# 多线程
# 让线程池创建100个线程
with ThreadPoolExecutor(100) as t:
# 在启用的线程中执行100次work()方法
[t.submit(work) for i in range(100)]
print('多线程', end='')
多进程:
多进程不用池是因为在创建进程池时会限制进程创建数量,这里为了演示会超过限制报错因此直接没用,如果你想用的话直接把线程的ThreadPoolExecutor换成ProcessPoolExecutor就行了非常简单
import multiprocessing
def work():
res = 0
for i in range(100000000):
res += i
def main_process():
# 多进程
# 创建100个进程对象,每个对象执行work()方法
M = [multiprocessing.Process(target=work) for i in range(100)]
for m in M:
m.start()
for m in M:
m.join()
print('多进程', end='')
由于GIL锁的存在,在CPython中只能有一个线程执行任务,假如一个计算密集型的任务需要 10s 的执行时间,总共有4个这样的任务
多进程: 需要开启 4 个进程,但是 4 个 CPU 并行,最终只需要消耗 10s 多一点的时间。
多线程: 只需要开1 个进程,这个进程开启 4 个线程,开启线程所消耗的资源很少,但是由于最终执行是只有一个 CPU 可以工作,所以最终消耗 40s 多的时间。
废话不多说直接上代码
import multiprocessing
import time
from concurrent.futures import ThreadPoolExecutor
def work():
res = 0
for i in range(100000000):
res += i
def main_thread():
# 多线程
with ThreadPoolExecutor(10000) as t:
[t.submit(work) for i in range(10000)]
print('多线程', end='')
def main_process():
# 多进程
M = [multiprocessing.Process(target=work) for i in range(100)]
for m in M:
m.start()
for m in M:
m.join()
print('多进程', end='')
def main(work_task):
s_time = time.time()
work_task()
e_time = time.time()
print(f'用时{e_time - s_time}秒')
if __name__ == '__main__':
main(main_process)
main(main_thread)
结果:
假如是多个 IO密集型 的任务 (例如input()
,time.sleep()
)CPU 大多数时间是处于闲置状态,频繁的切换
多进程: 进程进行切换需要消耗大量资源
多线程: 线程进行切换并不需要消耗大量资源,即使有GIL锁的存在,最终也会以量取胜多进程
在刚刚的计算密集型测试中,笔者吃了个饭才跑完多线程的测试,这次给线程老弟也上上强度,直接sleep一万次
import multiprocessing
import time
from concurrent.futures import ThreadPoolExecutor
def work():
time.sleep(1)
def main_thread():
# 多线程
with ThreadPoolExecutor(10000) as t:
[t.submit(work) for i in range(10000)]
print('多线程', end='')
def main_process():
# 多进程
M = [multiprocessing.Process(target=work) for i in range(10000)]
for m in M:
m.start()
for m in M:
m.join()
print('多进程', end='')
def main(work_task):
s_time = time.time()
work_task()
e_time = time.time()
print(f'用时{e_time - s_time}秒')
if __name__ == '__main__':
main(main_process)
main(main_thread)