多進程、多線程與協程
目錄
- 代碼整理
- 進程池
- 多線程
- 線程池
- 協程
- 應用場景
- 概述
- 確定線程池大小
- 確定進程池大小
- 解決方案
- 進一步理解
- 前言
- 多進程&多線程
- 概述
- 優劣
- 區別
- 線程池作用&原理
- 線程池作用
- 線程池原理
- 參考內容
- 總結
一、代碼整理
1.1 進程池
from multiprocessing import Pool
import os, time, random
def long_time_task(name):
print('Run task %s (%s)...' % (name, os.getpid()))
start = time.time()
time.sleep(random.random() * 3)
end = time.time()
print('Task %s runs %0.2f seconds.' % (name, (end - start)))
if __name__=='__main__':
print('Parent process %s.' % os.getpid())
p = Pool(4)
for i in range(5):
p.apply_async(long_time_task, args=(i,))
print('Waiting for all subprocesses done...')
p.close()
p.join()
print('All subprocesses done.')
1.2 多線程
import time, threading
def loop():
print('thread %s is running...' % threading.current_thread().name)
n = 0
while n < 5:
n = n + 1
print('thread %s >>> %s' % (threading.current_thread().name, n))
time.sleep(1)
print('thread %s ended.' % threading.current_thread().name)
print('thread %s is running...' % threading.current_thread().name)
t = threading.Thread(target=loop, name='LoopThread')
t.start()
t.join()
print('thread %s ended.' % threading.current_thread().name)
1.3 線程池
from concurrent.futures import ThreadPoolExecutor
import urllib.request
import time
def fetch_url(url):
u = urllib.request.urlopen(url)
data = u.read()
print('data', data)
return data
pool = ThreadPoolExecutor(10)
start = time.time()
# Submit work to the pool
a = pool.submit(fetch_url, 'http://www.python.org')
b = pool.submit(fetch_url, 'http://www.pypy.org')
# Get the results back
x = a.result()
y = b.result()
end = time.time()
print('runtime %d' % (end - start))
1.4 協程
def consumer():
r = ''
while True:
n = yield r
if not n:
return
print('[CONSUMER] Consuming %s...' % n)
r = '200 OK'
def produce(c):
c.send(None)
n = 0
while n < 5:
n = n + 1
print('[PRODUCER] Producing %s...' % n)
r = c.send(n)
print('[PRODUCER] Consumer return: %s' % r)
c.close()
c = consumer()
produce(c)
二、應用場景
2.1 概述
多進程適合在 CPU 密集型操作(cpu 操作指令比較多,如位數多的浮點運算)。
多線程適合在 IO 密集型操作(讀寫數據操作較多的,比如爬蟲)。
協程間是協同調度的,這使得併發量數萬以上的時候,協程的性能是遠遠高於線程。
2.2 確定線程池大小
最佳線程數目 = ((線程等待時間+線程CPU時間)/線程CPU時間 )* CPU數目
2.3 確定進程池大小
最佳線程數目 = CPU數目,即一個 CPU 執行一個進程。
2.4 解決方案
多進程 + 協程
既充分利用多核,又充分發揮協程的高效率,可獲得極高的性能。
三、進一步理解
3.1 前言
copy
代碼,很容易就可以參考着用,可是明白底層的原理是非常之關鍵的。
3.2 多進程&多線程
3.2.1 概述
進程是操作系統分配資源(比如內存)的最基本單元
線程是操作系統能夠進行調度和分派的最基本單元。
多進程允許多個任務同時運行。
多線程允許將單個任務分成多個子任務運行。
3.2.2 優劣
多進程優點:穩定性高,因爲一個子進程崩潰了,不會影響主進程和其他子進程。
多線程缺點:任何一個線程掛掉都可能直接造成整個進程崩潰,因爲所有線程共享進程的內存。
3.2.3 區別
多進程中,同一個變量,各自有一份拷貝存在於每個進程中,互不影響。
多線程中,所有變量都由所有線程共享。
3.3 線程池作用&原理
3.3.1 線程池作用
有效的降低頻繁創建銷燬線程所帶來的額外開銷。
3.3.2 線程池原理
採用預創建的技術,在應用啓動之初便預先創建一定數目的線程。應用在運行的過程中,需要時可以從這些線程所組成的線程池裏申請分配一個空閒的線程,來執行一定的任務,任務完成後,並不是將線程銷燬,而是將它返還給線程池,由線程池自行管理。
四、參考內容
五、總結
代碼誰都會寫,但是底層懂纔是真的懂。