进程和协程基础

一、进程介绍
1、概念:
一个运行起来的程序/应用所占用的资源
进程是 操作系统资源分配的基本单位
2、注意:
一个程序运行后至少有一个进程,一个进程默认有一个线程 ,进程里面可以创建多
个线程, 线程是依附在进程里面的, 没有进程就没有线程
3 、进程状态
就绪态:运行的条件都满足,正在等待cpu执行
执行态:cpu正在执行某功能
等待态:等待某些条件满足,如一个程序sleep了,就处于等待态
4、进程和线程的对比
功能
进程,能够完成多任务,比如 在一台电脑上能够同时运行
多个 QQ
线程,能够完成多任务,比如 一个 QQ 中的多个聊天窗口
定义的不同
进程是系统进行资源分配和调度的一个独立单位 .
线程是进程的一个实体 , CPU 调度和分派的基本单位 ,
是比进程更小的能独立运行的基本单位 . 线程自己基本上不拥有
系统资源 , 只拥有一点在运行中必不可少的资源 ( 如程序计数器 , 一组寄存器和栈 ), 但是它可与同属一个进程的其他的线程共享
进程所拥有的全部资源 .
区别
一个程序至少有一个进程 , 一个进程至少有一个线程
线程的划分尺度小于进程 ( 资源比进程少 ) ,使得多线程程
序的并发性高
进程在执行过程中拥有独立的内存单元,而多个线程共享
内存,从而极大地提高了程序的运行效率
线线程不能够独立执行,必须依存在进程中
二、进程的创建
1、进程模块 multiprocessing
类Process参数:
Process([group [, target [, name [, args [, kwargs]]]]])
target :如果传递了函数的引用,可以任务这个子进程就执行这里的代
args :给 target 指定的函数传递的参数,以元组的方式传递
kwargs :给 target 指定的函数传递命名参数
name :给进程设定一个名字,可以不设定
group :指定进程组,大多数情况下用不到
Process 创建的实例对象的常用方法:
start() :启动子进程实例(创建子进程)
is_alive() :判断进程子进程是否还在活着
join([timeout]) :是否等待子进程执行结束,或等待多少秒
terminate() :不管任务是否完成,立即终止子进程
2、创建进程
导包 from multiprocessing import Process
创建任务 /函数
创建进程 进程名 = Process(target = 函数名)
开启进程 进程名.start()
1
from multiprocessing import Process
2
import time
3
4
def func (name): 5
for i in range ( 3 ):
6
print ( 'hello world' , name)
7
time. sleep ( 1 )
8
9
if __name__ == '__main__' :
10
p = Process (target = func, kwargs = { 'name' : '123' }) # 创建进程 , 传参
同线程
11
p. start () # 开启进程
3、多进程间不共享全局变量
1
# 多进程不共享全局变量
2
num = 100
3
def func ():
4
global num
5
num ‐= 50
6
print ( ' 进程 1' , num)
7
8
def func1 ():
9
global num
10
num += 85
11
print ( ' 进程 2' , num)
12
13
if __name__ == '__main__' :
14
p = Process (target = func)
15
p1 = Process (target = func1)
16
p. start ()
17
p1. start ()
4、打印进程号 os.getpid()
1
from multiprocessing import Process
2
import os
3
import time
4
5
def run_proc ():
6
""" 子进程要执行的代码 """
7
print ( ' 子进程运行中, pid=%d...' % os. getpid ()) # os.getpid 获取当
前进程的进程号 8
print ( ' 子进程将要结束 ...' )
9
10
if __name__ == '__main__' :
11
print ( ' 父进程 pid: %d' % os. getpid ()) # os.getpid 获取当前进程的进
程号
12
p = Process (target = run_proc)
13
p. start ()
三、进程间的通信
1、使用 multiprocessing 模块中的 Queue 实现多进程间数据传递
2、Queue对象用到的方法
对象名 = Queue(n) 创建队列,n为可接收的消息数量,不写或为负表示没有
上限
对象名.put(item) -------------将item写入队列
对象名.get(True) -------------获取队列中的一条信息,然后将该
信息移除
对象名.empty() --------------判断队列是否为空
对象名.full() -----------------判断队列是否装满
对象名.qsize() ----------------返回队列包含的信息数量/队列长
1
def write (q):
2
q. put ( 'a' ) # 往队列中写入信息
3
print ( ' a 写入队列 ' )
4
5
def read (q):
6
if not q. empty (): # 判断队列是否是空的
7
value = q. get (True) # 获取队列中的信息,并将该条信息删除
8
print ( ' 从队列读出 ' , value)
9
10
if __name__ == '__main__' :
11
q = Queue () # 创建队列
12
p1 = Process (target = write, args = (q,)) # 创建进程
13
p2 = Process (target = read, args = (q,))
14
p1. start () # 开启进程
15
p1. join () # 等待子进程结束再结束 16
p2. start ()
17
p2. join ()
C:\Users\feifei\AppData\Local\Programs\Python\Python37\python.exe E:/H2002A/python
高级/进程.py
将a写入队列
从队列读出 a
进程已结束,退出代码 0
四、进程池 ------------ 快速批量创建进程
from muliprocessing import Pool
1、Pool中的函数
apply_async(函数名,参数args/kwds) ---------- 使用非阻塞方式
调用 func (并行执行,堵塞方式必须等待上一个进程退出才能执行下一个进
程), args 为传递给 func 的参数列表, kwds 为传递给 func 的关键字参数列表;
close() ------------关闭进程池,使其不再接收新的任务
join() ------------等待子进程结束, 必须写再close 或 terminata
之后
terminate() ----------- 不管任务是否完成,立即结束
2、创建进程池
1
from multiprocessing import Pool
2
import os, time
3
def worker (msg):
4
print ( "%s 开始执行 , 进程号为 %d" % (msg,os. getpid ()))
5
time. sleep ( 1 )
6
7
if __name__ == '__main__' :
8
po = Pool ( 3 ) # 定义一个进程池,最大进程数 3
9
for i in range ( 10 ):
10
# Pool (). apply_async ( 要调用的目标 ,( 传递给目标的参数元祖 ,))
11
# 每次循环将会用空闲出来的子进程去调用目标
12
po. apply_async (worker,(i,))
13
14
print ( "‐‐‐‐start‐‐‐‐" )
15
po. close () # 关闭进程池,关闭后 po 不再接收新的请求
16
po. join () # 等待 po 中所有子进程执行完成,必须放在 close 语句之后 17
print ( "‐‐‐‐‐end‐‐‐‐‐" )
C:\Users\feifei\AppData\Local\Programs\Python\Python37\python.exe E:/H2002A/python
高级/进程.py
----start----
0 开始执行,进程号 9684
1 开始执行,进程号 2244
2 开始执行,进程号 14504
0 执行时间1.00
3 开始执行,进程号 9684
1 执行时间1.00
4 开始执行,进程号 2244
2 执行时间1.00
5 开始执行,进程号 14504
3 执行时间1.00
6 开始执行,进程号 9684
4 执行时间1.00
7 开始执行,进程号 2244
5 执行时间1.00
8 开始执行,进程号 14504
6 执行时间1.00
9 开始执行,进程号 9684
7 执行时间1.00
8 执行时间1.00
9 执行时间1.00
-----end-----
进程已结束,退出代码 0
一、协程
1、概念
协程,又称微线程
在不开辟线程的基础上完成多个任务按照一定顺序交替执行
2、优势
优势 01 :协程最大的优势就是极高的执行效率。因为子程序切换不是线程切
换,而是由程序自身控制,因此,没有线程切换的开销,和多线程比,线程数量
越多,协程的性能优势就越明显。(内部封装了 cpu 上下文)
优势 02 :不需要多线程的锁机制,因为只有一个线程,也不存在同时写变量
冲突,在协程中控制共享资源不加锁,只需要判断状态就好了,所以执行效率比
多线程高很多。
相比于进程和线程,协成的特点:协成可以在单个线程的基础上多个任务交
替执行,所以协程切换任务资源很小,效率高
3、基本协程的构建 ------------- 用yeild
1
import time
2
3
# 定义协程 1
4
def work_1 ():
5
while True:
6
print ( "work1..." )
7
time. sleep ( 0.1 )
8
yield
9
10
# 定义协程 2
11
def work_2 ():
12
while True:
13
print ( "work2..." )
14
time. sleep ( 0.1 )
15
yield
16
17
# 创建协程
18
g1 = work_1 ()
19
g2 = work_2 () 20
while True:
21
next (g1)
22
next (g2)
用yeild 和 send 实现生产者、消费者模型
1
def consumer (): # 消费者
2
r = ''
3
while 1 :
4
n = yield r
5
print ( ' 消费者消费 ' , n)
6
7
def product (c): # 生产者
8
c. send (None)
9
for i in range ( 1 , 6 ):
10
print ( ' 生产者生产 ' , i)
11
r = c. send (i)
12
c. close ()
13
14
c = consumer ()
15
product (c)
二、greenlet模块
1
import greenlet
2
import time
3
# greenlet 封装的是 yield ,为了让程序员更好的使用协程
4
# 任务 1
5
def work1 ():
6
for i in range ( 5 ):
7
print ( "work1...." )
8
time. sleep ( 0.3 )
9
# 切换到协程 2 执行对应的任务
10
g2. switch ()
11
12
# 任务 2
13
def work2 ():
14
for i in range ( 5 ): 15
print ( "work2...." )
16
time. sleep ( 0.3 )
17
# 切换到协程 1 执行对应的任务
18
g1. switch ()
19
20
# 创建协程指定对应的任务
21
g1 = greenlet. greenlet (work1)
22
g2 = greenlet. greenlet (work2)
23
# 启动并切换到指定协程执行对应的任务
24
g1. switch ()
消费者/生产者模型
1
from greenlet import greenlet
def consumer (): # 消费者 consumer
while True:
n = gr_produce. switch ()
print ( '[CONSUMER] Consuming %s...' % n)
def produce (): # 生产者 produce
for n in range ( 1 , 6 ):
print ( '[PRODUCER] Producing %s...' % n)
gr_consumer. switch (n)
gr_consumer = greenlet (consumer)
gr_produce = greenlet (produce)
# 切换到 consumer 中运行
gr_consumer. switch ()
三、gevent模块
gevent.spawn(func, *args, ...) 方法用来生成协程,他接受一个函数作为参数
gevent.joinall([t1, t2, ...]) 方法用来启动协程轮询并等待运行结果
gevent.sleep() 用来模拟一个 IO 操作,阻塞后自动切换到另一个协程执行
import gevent
def func1 ():
print ( '1 开始 ' )
gevent. sleep ( 8 ) # 模拟输入输出操作
print ( '1 结束 ' )
def func2 ():
print ( '2 开始 ' )
gevent. sleep ( 5 )
print ( '2 结束 ' )
def func3 ():
print ( '3 开始 ' )
gevent. sleep ( 3 )
print ( '3 结束 ' )
gevent. joinall ([ # joinall 启动协程轮询
gevent. spawn (func1), # spawn 创建协程
gevent. spawn (func2),
gevent. spawn (func3)])
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值