并发编程:
并发编程理论居多 实际代码很简单
必备知识点回顾:
● 计算机又叫电脑,即通电的大脑,发明计算机是为了让他通电之后能够像人一样去工作,并且它比人的工作效率更高,因为可以24小时不间断
●计算机五大组成部分
控制器
运算器
存储器
输入设备
输出设备
计算机的核心真正干活的是CPU(控制器+运算器=中央处理器)
●程序要想被计算机运行,它的代码必须要先由硬盘读到内存,之后cpu取指再执行
早期计算机:
早期处理cpu利用率的方法:
升级:
多道技术:
并发:看起来像同时执行的称之为并发
并行:真正意义上的同时执行
ps:
1、并行肯定是并发
2、单核的计算机肯定不能实现并行,但是可以实现并发!!
补充: 我们直接假设单核就是一个核,干活就一个人,不要考虑cpu里面的内核数
多道技术图解: (节省了多个程序运行的总耗时)
多道技术重点知识:
1、空间上的复用
多个程序公用一套计算机硬件( 比如 qq 微信 公用一台我的计算机)
2、时间上的复用
例如:洗衣服30s ,做饭50s,烧水30s
单道技术: 等衣服洗好再做饭再烧水
多道技术:做饭的同时进行洗衣服烧水(只需要完成耗时最长的任务)
切换 + 保存状态:
切换(cpu)分为两种情况:
1、当一个程序遇到IO操作时候,操作系统会剥夺该程序的CPU执行权限( 比如qq占据CPU 然后我又点了一下微信,然后操作系统会把qq的CPU拿回来让微信程序使用,也就是说qq占着茅坑不拉屎)
作用:提高了CPU的利用率,并且也不影响程序的执行效率
2、当一个程序长时间占用CPU的时候,操作系统也会剥夺该程序的CPU执行权限
作用:降低了程序的执行效率 原因:(原本时间 + 切换时间 + 再次运行程序的时间)
进程理论: (进程==程序)
必备知识点:
程序与进程的区别:
程序就是一堆躺在硬盘上的代码, 是‘’死‘’ 的
进程表示程序正在执行的过程,是活的。
进程调度:
1、先来先服务调度算法
对长作业有利,对短作业无益
2、短作业优先调度算法
对短作业有利,对长作业无益
3、时间片轮转法 + 多级反馈队列
进程运行的三状态图:
注意:在阻塞态如果程序一直呆着不运行的话 那么cpu就会拿走被其他程序运用,在阻塞中的程序要从新进入就绪态等候从新分配的cpu
用代码演示:
两对重要概念:
1 同步和异步
''' 描述的是任务的提交方式'''
同步:任务提交之后,原地等待任务的返回结果,等待的过程中不做任何事(干等)
程序层面上表现出来的感觉是卡住了
异步:任务提交之后,不原地等待任务的返回结果,直接去做其他的事情
问题: 我提交的任务结果如何获取?
任务的返回结果会有一个异步回调机制自动处理
2 阻塞非阻塞: (阻塞 : 就比如打开百度我们不输入信息 我们就会一直停留在百度的首页)
'''描述程序的运行状态'''
阻塞:阻塞态
非阻塞:就绪态 + 运行态
理想状态:我们应该让我们写的代码永远处于就绪态和运行态之间切换
上述概念的组合: 最高效的一种组合就是 异步非阻塞
同步的代码演示:
开启进程的两种方式:
# 第一种(常用)
from multiprocessing import Process # Process 是一个类
import time
def task(name):
print('%s is running' % name)
time.sleep(3)
print('%s is over' % name)
if __name__ == '__main__':
# 1 创建一个对象
res = Process(target=task, args=('juson',))
# 注意 : 容器类型(元组)哪怕里面只有1个元素 也要用逗号隔开
# 2 开启线程
res.start() # 告诉操作系统帮你创建一个进程 异步(任务提交之后不等待结果直接运行了下面的x)
print('主')
'''
windows 操作系统下 创建进程一定要在main内创建( 防止死循环)
因为windows下创建进程类似于模块的导入方式会从上往下依次执行代码还会再次执行进程1,2,3。。。(防止死循环)
linux系统中则是直接复制代码
'''
# 第二种方式: 类的继承
from multiprocessing import Process
import time
class MyProcess(Process):
def run(self): # 必须是run
print('hello bf girl')
time.sleep(1)
print('get out')
if __name__ == '__main__':
# 创建一个对象
res = MyProcess()
res.start()
print('主')
打印结果顺序如下: (先打印主 再打印run里面的结果)
总结:
'''创建的进程就是在内存中申请一块内存空间需要将代码丢进去
一个进程对应内存中的一块独立的内存空间
多个进程在内存中对应多个独立的内存空间
进程与进程之间的数据默认情况下是无法直接交互,如果想交互可以借助于第三方工具,模块
'''
join方法
怎么将主后打印出来呢?(join等待着p1的结果 然后再打印'主'任务)
from multiprocessing import Process
import time
def task(name):
print('%s is running' % name)
time.sleep(3)
print('%s is over' % name)
if __name__ == '__main__':
p1 = Process(target=task, args=('liu',))
p1.start()
p1.join() # 主进程等待子进程p运行的结果之后再继续往下执行
print('主')
=========================================================================
如果出现顺序不一样的情况(正常现象)
from multiprocessing import Process
import time
def task(name):
print('%s is running' % name)
time.sleep(3)
print('%s is over' % name)
if __name__ == '__main__':
p1 = Process(target=task, args=('liu',))
p2 = Process(target=task, args=('wen',))
p3 = Process(target=task, args=('jun',))
p1.start() # 这三个代码只是告诉操作系统帮你创建三个进程 但p1 p2 p3 的顺序操作系统不会帮你规划顺序
p2.start() # 所以有时候会发生顺序混乱
p3.start()
# p1.join()
print('主')
from multiprocessing import Process
import time
def task(name,n):
print('%s is running' % name)
time.sleep(n)
print('%s is over' % name)
if __name__ == '__main__':
p1 = Process(target=task, args=('liu', 1))
p2 = Process(target=task, args=('wen', 2))
p3 = Process(target=task, args=('jun', 3))
start_time = time.time()
p1.start()
p2.start()
p3.start()
p1.join()
p2.join()
p3.join()
print('主',time.time() - start_time) # 时间结果为3s左右 因为p1 p2 p3 三个程序同时运行的 在等p1的时候p2 p3 也已经
# 执行1s了 直到执行p3的时候已经执行2s了 p3只需要等1s就行了
for循环实现并发方法:
from multiprocessing import Process
import time
def task(name,i):
print('%s is running' % name)
time.sleep(i)
print('%s is over' % name)
if __name__ == '__main__':
start_time = time.time()
for i in range(1, 4): # 顾头不顾尾
p = Process(target=task, args=('子进程%s' %i ,i))
p.start()
p.join() # 因为for循环 所有join只能等着1任务结束后再等待2任务结束后再等待3任务 所以效率明显会降低 ( 明显将并发改写成了串行)
print('主', time.time() - start_time)
解决方法:
from multiprocessing import Process
import time
def task(name,i):
print('%s is running' % name)
time.sleep(i)
print('%s is over' % name)
if __name__ == '__main__':
start_time = time.time()
p_list = []
for i in range(1, 4): # 顾头不顾尾
p = Process(target=task, args=('子进程%s' %i ,i))
p.start()
p_list.append(p) # 先将三个进程对象放在一起
for p in p_list: # 然后拿出进程对象进行join 执行的时间差不多也就是时间最久的一个进程时间
p.join()
print('主', time.time() - start_time)