lesson14并发通信:
#视频1-作业讲解
#1,面向对象的方式实现多线程服务器
//14作业面向对象多线程server1.py:
1 import threading as th 2 import socket 3 4 server =socket.socket() 5 server.bind(('0.0.0.0',8080)) 6 server.listen(5) 7 8 #面向对象实现并发服务器 9 class MyThread(th.Thread): # 继承 10 def __init__(self,conn,addr): 11 super().__init__() # 调用父类的方法,生成一个进程 12 self.conn=conn 13 self.addr=addr 14 15 def run(self): 16 while True: 17 data = self.conn.recv(1024) 18 if data: 19 print('收到来自{}的消息{}'.format(self.addr,data.decode())) 20 self.conn.send(data) 21 else: 22 print('用户{}断开连接'.format(self.addr)) 23 self.conn.close() 24 break 25 26 while True: 27 conn, addr = server.accept() # 生成对等套接字 28 print('用户{}连接'.format(addr)) 29 process = MyThread(conn,addr) 30 process.start()
#运行:
和上节课一样
----------------------------------
18分钟:
#知识点
if __name__ == '__main__': //import导入其他文件时,不被运行程序,只导入函数
--------------------------------------------------------------------
#视频2-多进程通信问题
//14多进程通信问题2.py:
1 import multiprocessing as mp 2 3 #进程之间独立的,互不干扰的空间 4 a =1 5 6 def func(): 7 global a 8 a=2 9 print('子进程中a:',a) 10 11 p =mp.Process(target=func) 12 p.start() 13 p.join() 14 15 print('主进程中a:',a) #多进程里每个进程是独立的,所以主进程中 a =1,不变。
#运行:
子进程中a: 2
主进程中a: 1
18分钟:
一般常用的空间类型是:
1,mgr.list()
2,mgr.dict()
3,gr.Queue()
//代码
1 #例子2 2 import multiprocessing as mp 3 #解决进程中数据共享 4 5 #守护模式运行的进程 6 mgr =mp.Manager() #它是一个进程,专门用管理数据 7 list_proxy = mgr.list() #在这个用来通信的进程里面,开辟一个列表空间,用法和列表一样 8 9 list_proxy.append('niaaa') 10 11 def func(proxy): 12 print(proxy) 13 14 proxy.append('world') 15 print(proxy) 16 17 18 p =mp.Process(target=func,args=(list_proxy,)) 19 p.start() 20 p.join() 21 22 list_proxy.append('hello') 23 list_proxy.append('h') 24 # print(type(list_proxy)) 25 print(list_proxy) #子进程和主进程数据一样
#运行:
['niaaa']
['niaaa', 'world']
['niaaa', 'world', 'hello', 'h']
--------------------------------------------------------------------
#视频3-多线程通信问题
1,修改共享的数据需要加锁。使用锁来控制共享资源的访问
//14多线程通信问题3.py:
1 import threading as th 2 # 多线程空间共享,所以a改变,a=2,但还是会有其他问题,例如a+=1时,其他线程抢占改变值 3 # 要用锁来解决。防止其它线程访问变量 4 lock = th.Lock() 5 6 data =0 7 n =10000 8 9 def add(): 10 global data 11 for i in range(n): 12 lock.acquire() #第一种-加锁 13 data +=1 14 lock.release() #解锁 15 16 def sub(): 17 global data 18 for i in range(n): 19 with lock: #第二种加锁 20 data -=1 21 22 thread_add =th.Thread(target=add) #线程1 23 thread_sub =th.Thread(target=sub) #线程2 24 thread_add.start() 25 thread_sub.start() 26 27 thread_add.join() 28 thread_sub.join() 29 30 print(data)
#运行:
0
--------------------------------------------------------------------
#视频4-安全队列
queue.queue()创建一个队列
入队(put)
出队(get)
测试空(empty()近似)
测试满(full()近似)
队列长度(qsize()近似)
任务结束(task_done)
等待完成(join())
//14安全队列4.py:
1 import queue 2 3 q =queue.Queue(3) #创建队列,3ge 4 5 q.put('hello world') #入队列 6 q.put('111') 7 q.put('222') 8 9 print(q.full()) #队列是否满 10 11 while False==q.empty(): 12 print(q.get()) #出队列
#运行:
True
hello world
111
222
--------------------------------------------------------------------
#视频5-生产者和消费模型
生产者消费者模型
经典模型,必须掌握。
生产者(入队)--------消费者(出队) (生产者只管自己生产--满了阻塞,消费者只管自己消费,两者独立)
//14生产者和消费模型5.py:
1 import threading as th 2 import random 3 import queue 4 import time 5 6 #多线程 7 #生产者-只关心队列是否已满。没满则生产,慢了就阻塞 8 class Producer(th.Thread): 9 def __init__(self,queue): 10 super().__init__() 11 self.queue = queue 12 13 def run(self): 14 while True: 15 data = random.randint(0,99) #生产一个数据 16 self.queue.put(data) 17 print('生产了:',data) 18 time.sleep(1) 19 20 21 #消费者-只关心队列是否为空。不为空,则消费,为空则阻塞 22 class Concumer(th.Thread): 23 def __init__(self,queue): 24 super().__init__() 25 self.queue= queue 26 27 def run(self): 28 while True: 29 item =self.queue.get() #从队列中拿数据 30 print('消费者拿到:',item) 31 32 33 q =queue.Queue(5) #创建队列 34 p = Producer(q) #生产者 35 c =Concumer(q) #消费者 36 37 p.start() 38 c.start()
#运行:
生产了: 71
消费者拿到: 71
生产了: 52
消费者拿到: 52
生产了: 7
消费者拿到: 7
生产了: 4
消费者拿到: 4
生产了: 0
消费者拿到: 0
#作业:
参照多线程的生产者与消费者模式,
实现多进程的生产者与消费者模式。