多线程和多进程可以让程序拥有并行处理的能力,视实际情况不同程度的提升程序运行的效率。这篇博客以python来介绍多进程和多线程的使用。
多线程
我们创建一个简单的test函数来测试一下,功能就是打印输入的字符串,然后让程序停止2秒钟。
from threading import Thread
from time import sleep, time
def test(text):
print(text)
sleep(2) # 让程序沉睡2秒
# 开始添加线程
threads = []
# target:函数,args:函数的参数,以元组形式
threads.append(Thread(target=test, args=('第一次执行test函数',)))
threads.append(Thread(target=test, args=('第二次执行test函数',)))
s1 = time()
for t in threads:
# 设置为守护线程:主线程运行完毕之后,子线程仍然继续运行
t.setDaemon(True)
t.start() # 所有子线程同时启动
# 等待所有子线程运行完毕之后,再运行主程序
for t in threads:
t.join()
s2 = time()
print("程序运行时间:", s2 - s1)
我们创建了包含两个线程的线程池,一个线程执行一次test函数。可以看到,如果是正常的串并运行的话,是需要4秒的时间,但是通过多线程的并行,只需要2秒就完成了。
第一次执行test函数
第二次执行test函数
程序运行时间: 2.0180001258850098
多进程
我们还是使用上面的函数来测试,但是我们让输入的字符串也返回。
from multiprocessing import Pool
from time import sleep, time
def test(text):
print(text)
sleep(2) # 让程序沉睡2秒
return text
if __name__ == "__main__":
s1 = time()
# 列表的每个元素就是每个进程的函数的参数
# 这也意味着使用多进程的函数只能接受一个参数
paras = ['第一次执行test函数', '第二次执行test函数', '第三次执行test函数']
pool = Pool(3) # 新建含有3个进程的进程池
ret = pool.map(test, paras)
pool.close() # 关闭进程池
pool.join() # 阻塞住进程,等待子进程的运行完毕
s2 = time()
print("程序运行时间:", s2 - s1)
print("ret = ", ret)
同样,多进程的并行也可以达到2秒完成,但是可以看出比多线程多了0.3秒,主要是因为进程的启动需要花稍微多一点的时间
第一次执行test函数
第二次执行test函数
第三次执行test函数
程序运行时间: 2.312999963760376
ret = ['第一次执行test函数', '第二次执行test函数', '第三次执行test函数']
总结
- python的多线程和Java的是不一样的,python的多线程是在单核(单个cpu)下并行的,而Java会把多个线程分配到不同cpu的核心上;
- 多线程在IO密集(例如网络请求)的场景下,单个cpu的处理能力能够支撑起所有线程的并行,所以可以有很大的提升效果;
- 在计算密集(特别是计算较为复杂)的场景下,此时远远超出了单个cpu的处理能力,多线程往往不能有任何效果,此时就只能通过多进程了,因为一个进程对应一个cpu,即多进程会启动多个cpu来并行处理。
欢迎关注同名公众号:“我就算饿死也不做程序员”。
交个朋友,一起交流,一起学习,一起进步。