由于处理数据过多,程序运行很慢,就学习了一下python开启多线程与多进程的方法,虽然最后也没用上,但还是记录总结一下,以备不时之需。
传送门:进程与线程认识,进程与线程通俗理解
简言之,进程为资源分配的最小单元,线程为程序执行的最小单元
threading库中的Thread类可以方便地开启多线程运行,Thread类需要传入两个参数,target为需要执行的函数,args为函数的参数,本例中自定义的multithreading函数具有三个参数。
import threading
import time
import os
def multithreading(data, clss, k):
for i in range(5):
time.sleep(3 * (k + 1))
print(k, ":", clss, "--->", data,
"---> 线程id:", threading.get_ident(),
"---> 进程id:", os.getpid())
data = ["一念月落,一念身错,一念关山难涉过。棋逢过客,执子者不问因果。",
"奉上,唯愿去踏破善恶之叠浪,一心并肩赴跌宕",
"刺予我伤口,重生了魂魄,立剑的时候,疾骤的嘶吼"]
clss = ["一念关山", "奉上", "立剑"]
threads = []
for k in range(3):
t = threading.Thread(target=multithreading, args=(data[k], clss[k], k)) # 创建实例
threads.append(t)
t.start() # 启动线程运行
for t in threads:
t.join() # 等待所有线程执行完成
输出如下,三句话的线程id不同,但进程id一样。不同的线程抢占cpu资源,导致三句话打印混乱,由于延时差异,“立剑” 线程最后完成。
0 : 一念关山 ---> 一念月落,一念身错,一念关山难涉过。棋逢过客,执子者不问因果。 ---> 线程id: 8956 ---> 进程id: 1268
0 : 一念关山 ---> 一念月落,一念身错,一念关山难涉过。棋逢过客,执子者不问因果。 ---> 线程id: 8956 ---> 进程id: 1268
1 : 奉上 ---> 奉上,唯愿去踏破善恶之叠浪,一心并肩赴跌宕 ---> 线程id: 5640 ---> 进程id: 1268
2 : 立剑 ---> 刺予我伤口,重生了魂魄,立剑的时候,疾骤的嘶吼 ---> 线程id: 26068 ---> 进程id: 1268
0 : 一念关山 ---> 一念月落,一念身错,一念关山难涉过。棋逢过客,执子者不问因果。 ---> 线程id: 8956 ---> 进程id: 1268
1 : 奉上 ---> 奉上,唯愿去踏破善恶之叠浪,一心并肩赴跌宕 ---> 线程id: 5640 ---> 进程id: 1268
0 : 一念关山 ---> 一念月落,一念身错,一念关山难涉过。棋逢过客,执子者不问因果。 ---> 线程id: 8956 ---> 进程id: 1268
0 : 一念关山 ---> 一念月落,一念身错,一念关山难涉过。棋逢过客,执子者不问因果。 ---> 线程id: 8956 ---> 进程id: 1268
2 : 立剑 ---> 刺予我伤口,重生了魂魄,立剑的时候,疾骤的嘶吼 ---> 线程id: 26068 ---> 进程id: 1268
1 : 奉上 ---> 奉上,唯愿去踏破善恶之叠浪,一心并肩赴跌宕 ---> 线程id: 5640 ---> 进程id: 1268
1 : 奉上 ---> 奉上,唯愿去踏破善恶之叠浪,一心并肩赴跌宕 ---> 线程id: 5640 ---> 进程id: 1268
2 : 立剑 ---> 刺予我伤口,重生了魂魄,立剑的时候,疾骤的嘶吼 ---> 线程id: 26068 ---> 进程id: 1268
1 : 奉上 ---> 奉上,唯愿去踏破善恶之叠浪,一心并肩赴跌宕 ---> 线程id: 5640 ---> 进程id: 1268
2 : 立剑 ---> 刺予我伤口,重生了魂魄,立剑的时候,疾骤的嘶吼 ---> 线程id: 26068 ---> 进程id: 1268
2 : 立剑 ---> 刺予我伤口,重生了魂魄,立剑的时候,疾骤的嘶吼 ---> 线程id: 26068 ---> 进程id: 1268
multiprocessing库使用方法与threading库相同,其开启类为Process。
不过多进程运行似乎在windows下运行有点问题,参考 这篇文章 也没解决,似乎是windows下可以执行但无法显示,不过在linux下是可以显示的。
import threading
import multiprocessing
import time
import os
def my_multiprocess(data, clss, k):
for i in range(5):
time.sleep(3 * (k + 1))
print(k, ":", clss, "--->", data,
"---> 线程id:", threading.get_ident(),
"---> 进程id:", os.getpid())
data = ["一念月落,一念身错,一念关山难涉过。棋逢过客,执子者不问因果。",
"奉上,唯愿去踏破善恶之叠浪,一心并肩赴跌宕",
"刺予我伤口,重生了魂魄,立剑的时候,疾骤的嘶吼"]
clss = ["一念关山", "奉上", "立剑"]
processes = []
for k in range(3):
p = multiprocessing.Process(target=my_multiprocess, args=(data[k], clss[k], k))
processes.append(p)
p.start()
for p in processes:
p.join()
linux下运行的输出如下,三句话的进程id不同,但线程id一样了,这是可以的,线程id只要保证在进程中的唯一性就可以啦~
0 : 一念关山 ---> 一念月落,一念身错,一念关山难涉过。棋逢过客,执子者不问因果。 ---> 线程id: 140066568185664 ---> 进程id: 1889018
0 : 一念关山 ---> 一念月落,一念身错,一念关山难涉过。棋逢过客,执子者不问因果。 ---> 线程id: 140066568185664 ---> 进程id: 1889018
1 : 奉上 ---> 奉上,唯愿去踏破善恶之叠浪,一心并肩赴跌宕 ---> 线程id: 140066568185664 ---> 进程id: 1889019
0 : 一念关山 ---> 一念月落,一念身错,一念关山难涉过。棋逢过客,执子者不问因果。 ---> 线程id: 140066568185664 ---> 进程id: 1889018
2 : 立剑 ---> 刺予我伤口,重生了魂魄,立剑的时候,疾骤的嘶吼 ---> 线程id: 140066568185664 ---> 进程id: 1889020
0 : 一念关山 ---> 一念月落,一念身错,一念关山难涉过。棋逢过客,执子者不问因果。 ---> 线程id: 140066568185664 ---> 进程id: 1889018
1 : 奉上 ---> 奉上,唯愿去踏破善恶之叠浪,一心并肩赴跌宕 ---> 线程id: 140066568185664 ---> 进程id: 1889019
0 : 一念关山 ---> 一念月落,一念身错,一念关山难涉过。棋逢过客,执子者不问因果。 ---> 线程id: 140066568185664 ---> 进程id: 1889018
2 : 立剑 ---> 刺予我伤口,重生了魂魄,立剑的时候,疾骤的嘶吼 ---> 线程id: 140066568185664 ---> 进程id: 1889020
1 : 奉上 ---> 奉上,唯愿去踏破善恶之叠浪,一心并肩赴跌宕 ---> 线程id: 140066568185664 ---> 进程id: 1889019
1 : 奉上 ---> 奉上,唯愿去踏破善恶之叠浪,一心并肩赴跌宕 ---> 线程id: 140066568185664 ---> 进程id: 1889019
2 : 立剑 ---> 刺予我伤口,重生了魂魄,立剑的时候,疾骤的嘶吼 ---> 线程id: 140066568185664 ---> 进程id: 1889020
1 : 奉上 ---> 奉上,唯愿去踏破善恶之叠浪,一心并肩赴跌宕 ---> 线程id: 140066568185664 ---> 进程id: 1889019
2 : 立剑 ---> 刺予我伤口,重生了魂魄,立剑的时候,疾骤的嘶吼 ---> 线程id: 140066568185664 ---> 进程id: 1889020
2 : 立剑 ---> 刺予我伤口,重生了魂魄,立剑的时候,疾骤的嘶吼 ---> 线程id: 140066568185664 ---> 进程id: 1889020
so:多线程与多进程运行可以提高Python程序运行速度吗
Python的全局解释器锁(GIL)限制了同一时刻只有一个线程可以执行Python字节码,对于计算密集型任务,多线程往往无法提高程序的执行速度,但对于IO密集型任务,多线程可以利用IO阻塞等待时的空闲时间执行其他线程,提升运行效率。
多进程则可以有效地避免GIL的限制,允许同时执行多个进程,从而提高程序的执行速度。