那么什么是多线程, 什么时候使用它?
下面演示MultiProcessing不共享内存的代码,而Multi-Threading共享内存的代码。
在下面的代码中,我们检查列表中传递的数字是否为底数。我们将使用Multi-Threading多线程以及MultiProcessing多处理来做到这一点
我们创建了一个全局列表变量,prime_list存储所有质数。
通过所有数字list_of_num并检查数字是否为质数。
import threading
import time
prime_list=[]
def get_prime_numbers(numbers):
for num in numbers:
time.sleep(1)
if check_if_prime(num)==True:
prime_list.append(num)
return prime_list
def check_if_prime(num):
if num > 1:
# check for factors
for i in range(2,num):
if (num % i) == 0:
return False
break
else:
return True
# if input number is less than or equal to 1,then not a prime
else:
return False
def main():
start_time=time.perf_counter()
list_of_num=[9,13,12312, 121, 1913, 97, 57, 34, 37, 89, 81 , 87, 23, 27]
t1 = threading.Thread(target=get_prime_numbers, args=[list_of_num])
t1.start()
t1.join()
end_time=time.perf_counter()
print(f"Total time of Thread execution {round(end_time- start_time,4)} for the function ")
print(f'Prime numbers {prime_list} from {list_of_num}')
if __name__=='__main__':
main()
当线程共享内存或全局变量时,这些值将持久化,我们可以在程序的输出中看到这一点。
它的功能与上述功能相同,但我们使用了Multiprocessing库而不是线程。
对于Multiprocessing,创建 Process实例,然后将要执行的函数传递给目标,将所有参数传递给 args。这与多线程相同。
使用进程 process.start()
启动进程。
主进程等待子进程使用join()
完成。
import multiprocessing
import time
prime_list=[]
def get_prime_numbers(numbers):
for num in numbers:
time.sleep(1)
if check_if_prime(num)==True:
prime_list.append(num)
return prime_list
def check_if_prime(num):
if num > 1:
# check for factors
for i in range(2,num):
if (num % i) == 0:
return False
break
else:
return True
# if input number is less than or equal to 1 else not prime
else:
return False
def main():
start_time=time.perf_counter()
list_of_num=[9,13,12312, 121, 1913, 97, 57, 34, 37, 89, 81 , 87, 23, 27]
print("No. of CPU's ", multiprocessing.cpu_count())
p1 = multiprocessing.Process(target=get_prime_numbers, args=[list_of_num])
p1.start()
p1.join()
end_time=time.perf_counter()
print(f"Total time of Thread execution {round(end_time- start_time,4)} for the function ")
print(f'Prime numbers {prime_list} from {list_of_num}')
if __name__=='__main__':
main()
由于每个进程都有其全局变量的副本,因此我们看到全局变量(prime_list)为空
您也可以转到任务管理器,并在详细信息选项卡下查看多个 python .exe运行
ProcessPoolExector 是一种简单的方法来实现和生成多个进程,使用concurrent.futures
.
concurrent.futures
有一个抽象类执行器,它有两个具体的子类
ThreadPoolExecutor:用于多线程
ProcessPoolExecutor:用于多处理
在下面,我们使用ProcessPoolExecutor读取 CSV 文件,然后打印文件中的记录数。
import concurrent.futures
import time
import pandas as pd
def read_data(file):
t1= time.perf_counter()
data= pd.read_csv(file)
#data = data.sort_index(ascending=False)
time.sleep(1)
t2= time.perf_counter()
print(f"Took {round(t2-t1,4)} (sec) time to read data in {file}" )
return f' No. of Records in file {file} are {len(data)}'
def main():
start_time=time.perf_counter()
with concurrent.futures.ThreadPoolExecutor() as executor:
file_list=['pollution.csv', 'good_inpu.csv', 'iris.csv']
return_results=[executor.submit(read_data, file) for file in file_list]
for f in concurrent.futures.as_completed(return_results):
print(f.result())
end_time=time.perf_counter()
print(f"Total time of execution {round(end_time- start_time,4)} for the function")
if __name__=='__main__':
main()
对于 I/O 或网络密集型程序,请使用Threading
类或 ThreadPoolExecutor
进行多线程处理。
对于 Python 中的计算或 CPU 密集型程序并避免 GIL 限制,请使用multiprocessing
或 ProcessPoolExecutor
。