前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >多进程、多线程与协程

多进程、多线程与协程

作者头像
星辉
发布2019-09-29 17:39:18
4640
发布2019-09-29 17:39:18
举报

版权声明:本文为博主原创文章,遵循 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 线程池原理

采用预创建的技术,在应用启动之初便预先创建一定数目的线程。应用在运行的过程中,需要时可以从这些线程所组成的线程池里申请分配一个空闲的线程,来执行一定的任务,任务完成后,并不是将线程销毁,而是将它返还给线程池,由线程池自行管理。

四、参考内容

五、总结

代码谁都会写,但是底层懂才是真的懂。

本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2019-09-28 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 多进程、多线程与协程
    • 目录
      • 一、代码整理
        • 1.1 进程池
        • 1.2 多线程
        • 1.3 线程池
        • 1.4 协程
      • 二、应用场景
        • 2.1 概述
        • 2.2 确定线程池大小
        • 2.3 确定进程池大小
        • 2.4 解决方案
      • 三、进一步理解
        • 3.1 前言
        • 3.2 多进程&多线程
        • 3.3 线程池作用&原理
        • 四、参考内容
        • 五、总结
    领券
    问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档