测试样例:复制3部电影,每部大小为2.04G,比较复制耗时
import os
import threading
import datetime
t0 = datetime.datetime.now()
source_dir = "F:\多线程测试\origin"
dest_dir = "F:\多线程测试\copy"
# 3.读取源文件夹的文件列表
file_list = os.listdir(source_dir)
# 4.遍历文件列表实现拷贝
for file_name in file_list:
print(file_name, "--拷贝的进程pid是:", os.getpid())
print(file_name, "--拷贝的线程是:", threading.current_thread())
# 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
print(datetime.datetime.now()-t0)
1_同学麦娜丝.mkv --拷贝的进程pid是: 18016
1_同学麦娜丝.mkv --拷贝的线程是: <_MainThread(MainThread, started 308)>
2_同学麦娜丝.mkv --拷贝的进程pid是: 18016
2_同学麦娜丝.mkv --拷贝的线程是: <_MainThread(MainThread, started 308)>
3_同学麦娜丝.mkv --拷贝的进程pid是: 18016
3_同学麦娜丝.mkv --拷贝的线程是: <_MainThread(MainThread, started 308)>
0:03:21.734185
import threading
import os
import datetime
def copy_file(file_name, source_dir, dest_dir):
print(file_name, "--拷贝的进程pid是:", os.getpid())
print(file_name, "--拷贝的线程是:", threading.current_thread())
# 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__':
t0 = datetime.datetime.now()
# 1.定义源文件夹和目标文件夹
source_dir = "F:\多线程测试\origin"
dest_dir = "F:\多线程测试\copy"
# 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()
sub_thread.join()
print(datetime.datetime.now()-t0)
1_同学麦娜丝.mkv --拷贝的进程pid是: 17212
1_同学麦娜丝.mkv --拷贝的线程是:
0:01:05.723885
2_同学麦娜丝.mkv --拷贝的进程pid是: 17212
2_同学麦娜丝.mkv --拷贝的线程是:
0:02:11.567183
3_同学麦娜丝.mkv --拷贝的进程pid是: 17212
3_同学麦娜丝.mkv --拷贝的线程是:
0:03:20.944711
import multiprocessing
import os
import datetime
def copy_file(file_name, source_dir, dest_dir):
print(file_name, "--拷贝的进程pid是:", os.getpid())
# 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__':
t0 = datetime.datetime.now()
# 1.定义源文件夹和目标文件夹
source_dir = "F:\多线程测试\origin"
dest_dir = "F:\多线程测试\copy"
# 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()
sub_process.join()
print(datetime.datetime.now() - t0)
1_同学麦娜丝.mkv --拷贝的进程pid是: 17280
0:01:30.373696
2_同学麦娜丝.mkv --拷贝的进程pid是: 21340
0:02:51.638254
3_同学麦娜丝.mkv --拷贝的进程pid是: 14360
0:04:03.929954
比较:
方式 | 耗时 |
---|---|
单进程单线程 | 0:03:21 |
单进程多线程 | 0:03:20 |
多进程 | 0:04:03 |
在这个测试样例中,多进程最为耗时,可能的原因是多进程上下文切换更为耗时,同时本场景不属于CPU密集场景,并不适合多进程;单进程多线程和单进程单线程的耗时差不多,是我没想到的,感觉没有发挥出多线程的优势来,原因可能是本场景不涉及到CPU计算,纯IO密集,能提高的空间有限?也可能是复制的电影数量少了?
我尝试将复制的电影数量提高到6个,观察两种方式的耗时变化
方式 | 耗时 |
---|---|
单进程单线程 | 0:07:37 |
单进程多线程 | 0:07:40 |
好像不符合期望
代码参考:https://blog.csdn.net/weixin_44917390/article/details/119610760?spm=1001.2014.3001.5506(很不错)
————————————————————
2022.10.30.更新:
Python的多线程不是真正的多线程,因为GIL的原因,同一时间只能有一个线程在执行,哪怕时多核,换句话说,就算是十核的CPU执行多线程,也只能用到一个核,此时就是单核多线程。对比JAVA,多个线程能分发在多个核上同时运行(线程数≤核数)。
Python要想利用多核怎么办呢?
方法一:多进程。
方法二:将计算密集型任务用C语言来写,然后用Python来调用。
多说一句:C语言这类“很快”的语言最适合的就是计算密集型任务,在I/O密集任务上相比Python并没有绝对的优势。
那么Python的多线程还有用武之地吗?
在爬虫,web应用等I/O密集场景,还是有效果的。因为多线程的本质是避免CPU闲置浪费,此时就算单核多线程也能充分利用它的性能。
参考:
https://www.zhihu.com/question/23474039/answer/269526476?utm_source=wechatMessage_answer_bottom