知识点补充: 1、操作系统的调度算法: 时间片轮转法 多级反馈队列 2、同步异步(任务的提交方式): 同步:提交任务之后原地等待任务的返回结果,才能进行下一步操作 异步:提交任务之后不等待任务的返回结果,直接进行下一步操作 3、阻塞非阻塞 阻塞:程序处于阻塞态 非阻塞:程序处于运行或就绪态 4、进程理论: 进程:正在运行的程序 多道技术: 空间上的复用 多个程序共用一套硬件设备 时间上的复用 CPU来回切换:切换+保存状态 1、程序占用cpu时间过长会被操作系统强行剥夺走cpu的执行权限 2、程序的IO操作指的是: input 网络请求(recv accept) time.sleep 文件读写 print 5、创建进程的本质:在内存中申请一块独立的内存空间,需要申请内存空间,还需要拷贝代码
#1、进程间通信 #队列:先进先出 #堆栈:先进后出 #利用队列实现进程间通信 from multiprocessing import Queue q = Queue(5) #里面的参数代表最多放5个数据 q.put(1) #往队列里放数据 q.put(1) q.put(1) q.put(1) print(q.full()) #判断队列是否放满了,此时显示False,还有一个位置没放数据 q.put_nowait(2) #往队列里放数据, # q.put_nowait(2) #当超过队列里允许放置数据个数的最大值以后,系统会报错 # q.put(1) #当超过最大值,此时不会报错,只是程序会卡住,不会继续运行 q.get() #从队列里取数据 q.get() q.get() print(q.empty()) #当前的队列里面是否还存在数据,此时显示False q.get() q.get_nowait() #从队列里取值,因为还存在数据,所以正常取值 # q.get_nowait() #因为队列里面的值全部取完了,所以这次系统会报错 # q.get() #队列为空,get会在原地等待队列中放置数据 print(q.empty()) #此时显示True,队列里面所存的数据全部被取出
#2、基于队列实现进程间通信 from multiprocessing import Queue,Process def producer(q): q.put('我是造数据的') def consumer(q): print(q.get()) if __name__ == '__main__': q = Queue() p1 = Process(target=producer,args=(q,)) p2 = Process(target=consumer,args=(q,)) p1.start() p2.start()
#3、生产者消费者模型 生产者:生成数据 消费者:处理数据 解决供需不平衡的问题: 定义一个队列,用来存放固定数量的数据 解决生产者和消费者不需直接打交道,双方通过队列实现数据传输的问题 Queen,JoinableQueue :管道+锁,后者稍微高级一些 from multiprocessing import JoinableQueue,Process import random,time def producer(name,food,q): for i in range(5): data = '%s拉出了%s,%s'%(name,food,i) time.sleep(random.randint(1,3)) print(data) q.put(data) #将数据放入队列中 def consumer(name,q): while True: data = q.get() time.sleep(random.randint(1,3)) print('%s消化了%s'%(name,data)) q.task_done() #告诉队列,已经将数据取出并消化完毕 if __name__ == '__main__': q = JoinableQueue() #生产一个队列对象 a1 = Process(target=producer,args=('tank','披萨',q)) a2 = Process(target=producer,args=('egon','面包',q)) b1 = Process(target=consumer,args=('owen',q)) b2 = Process(target=consumer,args=('fuck',q)) a1.start() a2.start() b1.daemon = True b2.daemon = True b1.start() b2.start() #等待生产者生产完所有的数据 a1.join() a2.join() #等待队列里的数据全部取出 q.join() print('主进程') #可能是因为3.7版本的问题,导致终端输出的时候,多行数据再同一行打印,剩下一些空行???
#4、线程 1、什么是线程 进程:资源单位 线程:执行单位 二者的联系:每一个进程中会自带一个线程 2、线程存在的必要性 开启一个进程: 申请内存空间 耗时 将代码拷贝到申请的内存空间中 耗时 开启线程: 不需要申请内存空间 因此,开启线程的开销远远小于开进程!
5、开启线程的方式 #方式一: 通过函数 from threading import Thread import time def task(name): print('%s is running'%name) time.sleep(1) print('%s is over'%name) if __name__ == '__main__': #因为线程不需要加载模块,所以这一步操作可有可无 t = Thread(target=task,args=('michael',)) t.start() #开启线程的速度非常快,几乎代码执行完线程就已经开启 # time.sleep(0.5) print('主线程') #方式二: 类的继承 from threading import Thread import time class MyThread(Thread): def __init__(self,name): #涉及到父类方法的重写,最好先调用super() super().__init__() self.name = name def run(self): print('%s is running'%self.name) time.sleep(1) print('%s is over'%self.name) t = MyThread('michael') t.start() print('主线程')
#6、线程之间数据共享 from threading import Thread import os x = 100 def task(): global x x=99 print('子线程所对应的进程的pid',os.getpid()) #7280 t = Thread(target=task) t.start() t.join() #存在有无,都没有影响 print(x) #99 print('主线程所对应进程的pid',os.getpid()) #7280 #上述的操作可以说明这几点: # 1、线程之间共享的是进程的数据 # 2、线程本身是不存在pid的,存在的是上一级进程的pid
#7、线程互斥锁 from threading import Thread,Lock import time import random #下面为没有加锁的,导致所有线程拿到的数据是同一份,没有达到预期的效果 n = 10 def task(): global n tmp = n time.sleep(0.1) #存在延迟,导致所有线程拿到的n都是10,处理以后所有的返回值都是9 #若不存在延迟,最后的结果为n=0, 所有的线程都处理了数据,具体过程日后再谈 ???? n = tmp - 1 t_list = [] for i in range(10): t = Thread(target=task) t.start() t_list.append(t) for t in t_list: t.join() #让主线程等待10个子线程结束以后再运行自身 print(n) #n = 9 #加锁 mutex = Lock() n = 10 def task(): global n mutex.acquire() #加锁 让线程从并行改变为了串行 tmp = n time.sleep(0.1) n = tmp - 1 mutex.release() #释放锁 一个线程结束以后,其他的线程开始了竞争 t_list = [] for i in range(10): t = Thread(target=task) t.start() t_list.append(t) for t in t_list: t.join() print(n) #n=0
#8、线程的其他属性与方法 from threading import Thread,active_count,current_thread def task(name): print('%s is running'%name) time.sleep(1) print('%s is over'%name) t1 = Thread(target=task,args=('michael',)) t2 = Thread(target=task,args=('michael',)) t1.start() t2.start() print(active_count()) #当前存活的线程数,加上主线程 3 print(current_thread()) #产生了一个对象 t1.join() t2.join() print(active_count()) #回收了两个子线程,还剩下一个主线程 1
#9、守护进程 from threading import Thread,active_count import time def task(name): print('%s is running'%naem) time.sleep(0.1) print('%s is over'%name) t = Thread(target=task,args=('michael',)) t.daemon = True #主线程结束,守护线程也会立刻结束,然而在这场景,没什么具体的用处 t.start() print(active_count()) #没有延迟时,理论上为1 print('主') print(active_count()) #没有延迟时,理论上为1 可能是受限于计算机硬件的能力,软件比硬件发展快好多