声明:这部分好像是计算机系统里的内容,本人并未正式学过相关内容,以下内容均为学习python爬虫时所了解,算是学习笔记,有错误请大家及时指出!


目录

  • 对于三者的理解
  • 基本概念
  • 工作原理分析
  • python实现
  • 多进程
  • 多线程
  • 多协程
  • 补充(线程池和进程池)


对于三者的理解

基本概念

进程是应用程序的启动实例,进程拥有代码和打开的文件资源、数据资源、独立的内存空间。

线程是程序的实际执行者,一个进程至少包含一个主线程,也可以有更多的子线程,线程拥有自己的栈空间。

首先要明确的是进程(process)是一个资源单位,而线程(thread)是一个执行单位。**协程(coroutines)**是一种比线程更加轻量级的存在,正如一个进程可以拥有多个线程一样,一个线程可以拥有多个协程。总结:协程从属于线程,线程从属于进程。

python线程 进程 python进程线程协程_线程池

工作原理分析

对操作系统而言,线程是最小的执行单元,进程是最小的资源管理单元。无论是进程还是线程,都是由操作系统所管理的。

协程不是被操作系统内核所管理的,而是完全由程序所控制,也就是在用户态执行。这样带来的好处是性能大幅度的提升,因为不会像线程切换那样消耗资源。协程不是进程也不是线程,而是一个特殊的函数,这个函数可以在某个地方挂起,并且可以重新在挂起处外继续运行。所以说,协程与进程、线程相比并不是一个维度的概念。

程序开始运行后,会创建一个或多个进程(一般是一个),在进程又会在进程中创建一个或多个线程(一般也是一个)。

线程具有五种状态:初始化、可运行、运行中、阻塞、销毁

python线程 进程 python进程线程协程_线程池_02


假如不引入协程,线程在进行时会遇到许多阻塞(多为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线程 进程 python进程线程协程_python_03

多线程

多线程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线程 进程 python进程线程协程_python_04

多协程

多协程程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)#打印运行时间

程序运行结果:

python线程 进程 python进程线程协程_多进程_05


程序运行只用了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')

运行结果部分截图

多个线程交叉杂乱执行(不受程序员控制

python线程 进程 python进程线程协程_python_06