一、进程介绍
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)])