声明:这部分好像是计算机系统里的内容,本人并未正式学过相关内容,以下内容均为学习python爬虫时所了解,算是学习笔记,有错误请大家及时指出!
目录
- 对于三者的理解
- 基本概念
- 工作原理分析
- python实现
- 多进程
- 多线程
- 多协程
- 补充(线程池和进程池)
对于三者的理解
基本概念
进程是应用程序的启动实例,进程拥有代码和打开的文件资源、数据资源、独立的内存空间。
线程是程序的实际执行者,一个进程至少包含一个主线程,也可以有更多的子线程,线程拥有自己的栈空间。
首先要明确的是进程(process)是一个资源单位,而线程(thread)是一个执行单位。**协程(coroutines)**是一种比线程更加轻量级的存在,正如一个进程可以拥有多个线程一样,一个线程可以拥有多个协程。总结:协程从属于线程,线程从属于进程。
工作原理分析
对操作系统而言,线程是最小的执行单元,进程是最小的资源管理单元。无论是进程还是线程,都是由操作系统所管理的。
协程不是被操作系统内核所管理的,而是完全由程序所控制,也就是在用户态执行。这样带来的好处是性能大幅度的提升,因为不会像线程切换那样消耗资源。协程不是进程也不是线程,而是一个特殊的函数,这个函数可以在某个地方挂起,并且可以重新在挂起处外继续运行。所以说,协程与进程、线程相比并不是一个维度的概念。
程序开始运行后,会创建一个或多个进程(一般是一个),在进程又会在进程中创建一个或多个线程(一般也是一个)。
线程具有五种状态:初始化、可运行、运行中、阻塞、销毁
假如不引入协程,线程在进行时会遇到许多阻塞(多为IO操作),遇到阻塞时线程无法“前进”,有时候这些等待是没有意义的(比如爬虫爬取资源时需要与网站服务器进行会话,这个过程是很耗时间的,这段时间完全可以进行其他操作),为了减少无意义的等待,程序员在编写代码时可以将一些函数协程化(自己编的词汇),当一个协程(即已被协程化的函数)进入等待时,计算机就会跳出这个协程,将这个函数“挂起”,去执行另外一个协程。计算机会在多个协程之间反复切换,减少等待时间,提高程序运行效率。
python实现
多进程
多进程python实现:
from multiprocessing import Process
def func():#测试函数
for i in range(1000):
print('func',i)
if __name__=='__main__':
p=Process(target=func)#新建进程
p.start()#启动新进程
for i in range(1000):#“主进程”
print('main',i)
代码分析
首先导入相关的库
from multiprocessing import Process
新建一个进程,并让函数func()在该进程中执行
p=Process(target=func)#新建进程
p.start()#启动新进程
测试结果部分截图
两个进程交叉杂乱执行(不受程序员控制)
多线程
多线程python实现:
from threading import Thread
def func():#测试函数
for i in range(100):
print('func',i)
if __name__=='__main__':
t=Thread(target=func)#新建线程
t.start()#启动新线程
for i in range(100):#“主线程”
print('main',i)
代码分析
导入相关库
from threading import Thread
新建一个线程,并让函数func()在该线程中执行
t=Thread(target=func)#新建线程
t.start()#启动新线程
测试结果部分截图
两个线程交叉杂乱执行(不受程序员控制)
多协程
多协程程python实现:
(代码有注释就不分析了)
import asyncio#实现协程所需的库
import time#测试程序运行时间用
async def func1():#协程1
print('我是C++')
#通过睡眠函数模拟函数将线程阻塞
#运行到这时将函数挂起去执行其他函数
await asyncio.sleep(4)
print('我是C++')
async def func2():#协程2
print('我是java')
#通过睡眠函数模拟函数将线程阻塞
#运行到这时将函数挂起去执行其他函数
await asyncio.sleep(3)
print('我是java')
async def func3():#协程3
print('我是python')
#通过睡眠函数模拟函数将线程阻塞
#运行到这时将函数挂起去执行其他函数
await asyncio.sleep(3)
print('我是python')
async def main():
'''新建三个协程任务'''
f1=func1()
f2=func2()
f3=func3()
tasks=[
f1,f2,f3
]
await asyncio.wait(tasks)#将三个任务交给main()函数
if __name__=='__main__':
t1=time.time()#计时
asyncio.run(main())#启动协程
t2=time.time()#计时
print(t2-t1)#打印运行时间
程序运行结果:
程序运行只用了4点多秒,如果不采用协程,三个函数睡眠时间总和为10秒,程序运行时间将超过10秒,所以协程极大的提高了程序执行的效率。
补充(线程池和进程池)
python实现(以线程池为例,进程池同理)
#导入相关库,ThreadPoolExecutor为线程池,ProcessPoolExecutor为进程池
from concurrent.futures import ThreadPoolExecutor,ProcessPoolExecutor
def func(name):#测试函数
for i in range(100):
print(name,i)
if __name__=='__main__':
with ThreadPoolExecutor(20) as TP:#创建一个有20个线程的线程池
for i in range(20):
#将func()函数交给线程池中的线程
TP.submit(func,name=f"线程{i}")
print('over')
运行结果部分截图
多个线程交叉杂乱执行(不受程序员控制)