多进程、多线程与协程
- 2019 年 10 月 10 日
- 笔记
版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/y_silence_/article/details/101605333
多进程、多线程与协程
目录
- 代码整理
- 进程池
- 多线程
- 线程池
- 协程
- 应用场景
- 概述
- 确定线程池大小
- 确定进程池大小
- 解决方案
- 进一步理解
- 前言
- 多进程&多线程
- 概述
- 优劣
- 区别
- 线程池作用&原理
- 线程池作用
- 线程池原理
- 参考内容
- 总结
一、代码整理
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 线程池原理
采用预创建的技术,在应用启动之初便预先创建一定数目的线程。应用在运行的过程中,需要时可以从这些线程所组成的线程池里申请分配一个空闲的线程,来执行一定的任务,任务完成后,并不是将线程销毁,而是将它返还给线程池,由线程池自行管理。
四、参考内容
五、总结
代码谁都会写,但是底层懂才是真的懂。