Python 線程與進程
Python由于有全鎖局的存在(同一時間只能有一個線程執(zhí)行)雏赦,并不能利用多核優(yōu)勢挎袜。所以助琐,如果程序的多線程進程是CPU密集型的符隙,那多線程并不能帶來效率上的提升憎账,相反還可能會因為線程的頻繁切換套硼,導致效率下降;如果是IO密集型胞皱,多線程進程可以利用IO阻塞等待時的空閑時間執(zhí)行其他線程邪意,提升效率看政。
但我們總會有在程序中實現多并發(fā)來提升程序運行效率的情形。在這些情形下抄罕,可以適當的利用多進程來實現提升效率允蚣。
另外,python中呆贿,為了解決網絡請求密集中嚷兔,延時等待的問題,我們還可是使用協程來提交效率。
在于IO密集型程序中饱狂,多線程應用較多惜颇。
但在網絡請求密集中,協程比多線程強上很多壶运。
在CPU密集中,還是進程應用更多浪秘。
以下是三個例子:
線程:
#!/usr/bin/python
# -*- coding: UTF-8 -*-
import threading
import time, datetime
# 為線程定義一個函數
def print_time(thread_name):
for i in range(3):
now = datetime.datetime.now()
print(now, thread_name)
time.sleep(1)
# 不帶線程處理的程序
for i in range(5):
threadname = "threadName" + str(i)
print_time(threadname)
#線程處理
# for i in range(5):
# threadname = "threadName"+str(i)
# t = threading.Thread(target=print_time(threadname))
# t.start()
運行發(fā)現蒋情,不帶線程處理的程序和線程處理的程序運行順序是一樣的:
/Library/Frameworks/Python.framework/Versions/3.6/bin/python3.6 /Users/caobo/PycharmProjects/ThreadTest/threadTest.py
2017-11-08 11:55:32.889184 threadName0
2017-11-08 11:55:33.890456 threadName0
2017-11-08 11:55:34.894145 threadName0
2017-11-08 11:55:35.899107 threadName1
2017-11-08 11:55:36.900408 threadName1
2017-11-08 11:55:37.903821 threadName1
2017-11-08 11:55:38.907008 threadName2
2017-11-08 11:55:39.909538 threadName2
2017-11-08 11:55:40.914680 threadName2
2017-11-08 11:55:41.918500 threadName3
2017-11-08 11:55:42.921579 threadName3
2017-11-08 11:55:43.925748 threadName3
2017-11-08 11:55:44.928359 threadName4
2017-11-08 11:55:45.931913 threadName4
2017-11-08 11:55:46.932414 threadName4
Process finished with exit code 0
每個線程執(zhí)行完需要3秒,依次執(zhí)行線程耸携,總耗時15秒棵癣。
進程
# 進程處理
if __name__ == "__main__":
for i in range(5):
threadName = "threadName" + str(i)
p = multiprocessing.Process(target=print_time, args=(threadName,))
p.start()
進程處理運行結果如下:
/Library/Frameworks/Python.framework/Versions/3.6/bin/python3.6 /Users/caobo/PycharmProjects/ThreadTest/threadTest.py
2017-11-08 11:58:44.045175 threadName0
2017-11-08 11:58:44.046196 threadName1
2017-11-08 11:58:44.047036 threadName2
2017-11-08 11:58:44.048071 threadName3
2017-11-08 11:58:44.049010 threadName4
2017-11-08 11:58:45.045841 threadName0
2017-11-08 11:58:45.046783 threadName1
2017-11-08 11:58:45.048291 threadName2
2017-11-08 11:58:45.048476 threadName3
2017-11-08 11:58:45.050095 threadName4
2017-11-08 11:58:46.046989 threadName0
2017-11-08 11:58:46.047063 threadName1
2017-11-08 11:58:46.048629 threadName2
2017-11-08 11:58:46.049239 threadName3
2017-11-08 11:58:46.050937 threadName4
Process finished with exit code 0
每個進程執(zhí)行完需要3秒,并發(fā)執(zhí)行線程夺衍,總耗時3秒狈谊。
進程池
# 進程池處理
if __name__ == "__main__":
pool = multiprocessing.Pool(processes=4)
for i in range(5):
threadName = "threadName" + str(i)
pool.apply_async(print_time, (threadName,))
pool.close()
pool.join()
print("Sub-process(es) done.")
進程池處理結果如下:
/Library/Frameworks/Python.framework/Versions/3.6/bin/python3.6 /Users/caobo/PycharmProjects/ThreadTest/threadTest.py
2017-11-08 12:01:03.557402 threadName0
2017-11-08 12:01:03.557552 threadName1
2017-11-08 12:01:03.557686 threadName2
2017-11-08 12:01:03.557827 threadName3
2017-11-08 12:01:04.558322 threadName2
2017-11-08 12:01:04.558306 threadName0
2017-11-08 12:01:04.558311 threadName1
2017-11-08 12:01:04.558322 threadName3
2017-11-08 12:01:05.558841 threadName1
2017-11-08 12:01:05.558833 threadName2
2017-11-08 12:01:05.558841 threadName0
2017-11-08 12:01:05.558845 threadName3
2017-11-08 12:01:06.560105 threadName4
2017-11-08 12:01:07.561340 threadName4
2017-11-08 12:01:08.561577 threadName4
Sub-process(es) done.
Process finished with exit code 0
由于設置了進程并發(fā)的數量為4,所以沟沙,前三秒執(zhí)行的都是前四個進程的內容(每個進程執(zhí)行完需要三秒)河劝,進程5只能在前四個進程執(zhí)行完成之后,才開始執(zhí)行矛紫∈晗梗總耗時6秒。
修改進程并發(fā)數量為5:
# 進程池處理
if __name__ == "__main__":
pool = multiprocessing.Pool(processes=5)
for i in range(5):
threadName = "threadName" + str(i)
pool.apply_async(print_time, (threadName,))
pool.close()
pool.join()
print("Sub-process(es) done.")
運行結果如下:
/Library/Frameworks/Python.framework/Versions/3.6/bin/python3.6 /Users/caobo/PycharmProjects/ThreadTest/threadTest.py
2017-11-08 12:12:17.210982 threadName0
2017-11-08 12:12:17.211084 threadName1
2017-11-08 12:12:17.211188 threadName2
2017-11-08 12:12:17.211335 threadName3
2017-11-08 12:12:17.211451 threadName4
2017-11-08 12:12:18.211480 threadName0
2017-11-08 12:12:18.211481 threadName2
2017-11-08 12:12:18.211480 threadName1
2017-11-08 12:12:18.211785 threadName3
2017-11-08 12:12:18.211787 threadName4
2017-11-08 12:12:19.211773 threadName2
2017-11-08 12:12:19.211784 threadName0
2017-11-08 12:12:19.212676 threadName1
2017-11-08 12:12:19.212679 threadName4
2017-11-08 12:12:19.212679 threadName3
Sub-process(es) done.
Process finished with exit code 0
修改設置進程并發(fā)的數量為5含衔,所以煎娇,所有5個進程能夠同步執(zhí)行。每個進程執(zhí)行完需要三秒贪染,總耗時3秒缓呛。