并发编程
进程基础(操作系统中的概念)
进程它是操作系统总最重要的概念,也是最基本的一个概念
线程也是操作系统中得一个很重要的概念
进程和线程都是有操作系统来调度使用的,我们程序员是不能控制的,这里就设计到调度算法
什么是进程? 线程? 什么是程序?
# 进程和程序是两码事、完全不一样
程序:其实一个死的东西、一堆代码就是程序,它也没有生命周期
进程:它是有生命周期的,这个任务做完,进程就不存在了
"""
厨师做饭,厨师做一道菜、应该有菜谱,安装菜谱的程序一步一步的做,在这个过程中,菜谱就是程序,程序就是路程. 做菜的过程就是进程,厨师就是线程,如果做菜完毕了,进程就不存在了,线程是进程中实际做事儿的.
"""
# 在一个进程中,可以有多个线程,一个进程中只有一个线程,也是可以的。
# 一个进程中至少要有一个线程
进程和线程他们都是有操作系统来调度的,程序员级别是没办法来调度的,协程就是程序员级别的,协程的调度它就是有我们程序员自己来调度的,在操作系统中是没有协程这个概念的,是我么人为的抽象出来的
进程 >>> 线程 >>> 协程
他们三个消耗资源的对比:进程 >>> 线程 >>> 协程
# 单个CPU一次只能运行一个任务。
http://www.ruanyifeng.com/blog/2013/04/processes_and_threads.html
进程调度算法(四种算法)
CPU的工作机制:
1. 遇到I/O的时候,CPU会交出执行权限
2. 当CPU遇到耗时比较长的时候,也会自动交出执行权限,切换到其他任务
I/O密集型
"""他会被时间所阻塞,不会占用大量的CPU资源,比如sleep(3)"""
计算密集型
"""不占用大量的时候,会占用大量的CPU资源,这种情况就是计算密集型,没有时间的大量消耗"""
for i in range(10000000):
i+=1
一、先来先服务调度算法
二、短作业优先调度算法
三、时间片轮转法
四、多级反馈队列
进程的并行和并发概念
并行:统一时刻同时运行
# 如果CPU是单核的,同一时刻能不能做到同时执行多个任务,不能
# 如果是多核的,统一时刻就能够做到了
# 核是2,同一时刻最多执行2个任务
# 核是4个,同一时刻最多执行4个任务
并发:一段时间内看起来是同时运行
# 如果是单核的CPU,你说,听歌、看视频、浏览网页能不能我一起操作? 能的,cpu的切换达到的
生活中有哪些是并发的例子:
淘宝的双11
"""面试题:你对高并发有什么见解? 聊聊高并发? 你如何解决?"""
同步异步阻塞和非阻塞
同步:每一次的运行都要依赖于上一步的结果
异步:每次的运行结果不依赖于上次的结果
"""异步的效率更高,同步的就更低了"""
阻塞
非阻塞
异步+非阻塞 # 是效率最高的
同步+阻塞 # 是效率最低的
如何创建进程
from multiprocessing import Process
def task():
with open('a.txt', 'w', encoding='utf-8') as f:
f.write('helloworld')
"""现在这个写法还没有开启进程"""
"""Windows平台上必须写在这个里面"""
if __name__ == '__main__':
p = Process(target=task) # 实例出来一个进程类, 让这个进程执行task任务
p.start() # 真正的开启进程
Process类的参数
from multiprocessing import Process
def task(name, age, gender):
print(name, age, gender)
with open('a.txt', 'w', encoding='utf-8') as f:
f.write('helloworld')
"""现在这个写法还没有开启进程"""
"""Windows平台上必须写在这个里面"""
if __name__ == '__main__':
"""
group=None, target=None, name=None, args=(), kwargs={},
*, daemon=None
"""
p = Process(target=task, name='process-2', args=(), kwargs={'name':'jerry', 'age':20, 'gender':'male'}) # 实例出来一个进程类, 让这个进程执行task任务
p.start() # 真正的开启进程
# 操作系统是负责把这个进程开起来
# 开启一个进程来执行task任务,真正是谁在执行这个任务,是线程,进程里面至少要有一个线程
"""进程的几个属性:1. 进程名 2. 进程号pid kill """
# 如何查看进程的名称
print(p.name) # Process-1
# 怎么改进程名字
# p.name = '这是新的进程名'
# print(p.name) # 这是新的进程名
Process类的几个方法
from multiprocessing import Process
import time
def task(name, age, gender):
print(name, age, gender)
# with open('a.txt', 'w', encoding='utf-8') as f:
# f.write('helloworld')
time.sleep(3)
print("子进程的代码")
"""现在这个写法还没有开启进程"""
"""Windows平台上必须写在这个里面"""
if __name__ == '__main__':
"""
group=None, target=None, name=None, args=(), kwargs={},
*, daemon=None
"""
# 子进程 主进程
"""只是通知操作系统去开进程,并不是立马把进程开起来,他是需要消耗一定的时间的,侧面的反应了开启进程其实消耗很大"""
p = Process(target=task, name='process-2', args=(), kwargs={'name':'jerry', 'age':20, 'gender':'male'}) # 实例出来一个进程类, 让这个进程执行task任务
p.start() # 真正的开启进程
# 操作系统是负责把这个进程开起来
# 开启一个进程来执行task任务,真正是谁在执行这个任务,是线程,进程里面至少要有一个线程
"""进程的几个属性:1. 进程名 2. 进程号pid kill """
# 如何查看进程的名称
# print(p.name) # Process-1
# 怎么改进程名字
# p.name = '这是新的进程名'
# print(p.name) # 这是新的进程名
## 如何查看进程号
# print(p.pid) # process id
# print(p.is_alive()) # True
# p.terminate() # 杀死进程,结束任务
# import time
# time.sleep(1)
# print(p.is_alive())
p.join() # 等待子进程的代码全部执行完毕,在走主进程的
print("主进程的代码执行完毕")
如何开启多进程
多进程就意味着可以同时做多个任务嘛, 一个进程做一个任务,多个进程肯定是做多个任务
from multiprocessing import Process
import time
def task(name):
# print(name)
# with open('a.txt', 'a', encoding='utf-8') as f:
# f.write('helloworld')
print("子进程")
time.sleep(1)
if __name__ == '__main__':
"""理论上你是可以一直开进程,单是你需要考虑资源的消耗情况"""
start_time = time.time()
ll = []
for i in range(10):
p=Process(target=task, kwargs={'name':'kevin'})
p.start()
# p.join() #
ll.append(p)
for j in ll:
j.join()
print("主进程, 总时间:", time.time() - start_time)
基于TCP协议的高并发程序
一个服务端不能够同时给多个客户端发送消息
import socket # python提供的socket模块
def task(conn):
while True:
try:
# 异常了一个bug,粘包现象
data = conn.recv(1024) # 括号里面写的是接收的字节数,最多接收1024个字节
if len(data) == 0:
continue
print(data) # 还是bytes类型
# 服务端开始给客户端也发送一个数据
conn.send(data.upper())
except Exception as e:
print(e)
break
conn.close()
from multiprocessing import Process
if __name__ == '__main__':
# 1. 买手机
# SOCK_STREAM ====> 代表的是TCP协议
# socket.socket(socket.AF_INET, socket.SOCK_STREAM)
# socket.socket(socket.AF_INET, socket.SOCK_DGRAM) # udp协议
server = socket.socket() # 默认是TCP协议
# 2. 买手机卡
# '0.0.0.0' =====> 代表允许任何的ip链接
# server.bind(('0.0.0.0', 8000)) # 服务端绑定一个地址
server.bind(('127.0.0.1', 8001)) # 服务端绑定一个地址
# 3. 开机
server.listen(1) # 监听,半连接池
print('服务端正在准备接收客户端消息:')
while True:
conn, client_addr = server.accept() # 接收, 程序启动之后,会在accept这里夯住,阻塞
p = Process(target=task, args=(conn,))
p.start()