一 、进程间通信(IPC机制)
队列:先进先出
堆栈:先进后出
利用队列实现进程间通信
from multiprocessing import Queue
q = Queue(5) # 产生一个最多能够存放五个数据的队列
# q.put(1) # 往队列中存放数据,如果存放的数据个数大于队列最大存储个数,程序会阻塞
# q.put(2)
# q.put(3)
# print(q.full())
q.put(4)
# q.put(5)
# print(q.full())
# for i in range(6):
# q.put(i)
# 存取数据
for i in range(5):
q.put(i) # for循环往队列里面存放数据
print(q.get()) # 取数据,get一次就取一个
print(q.get())
print(q.get())
q.get_nowait() # 在队列有数据的情况下,跟get取值一样,当队列没有数据的情况下,取值直接报错
# q.get_nowait():同q.get(False)
print(q.empty()) # 判断队列是否为空,需要注意的是,在并发的情况下,这个方法判断不准确!
print(q.get())
print(q.get())
print(q.empty())
# q.get_nowait()
# print(q.get()) # 如果队列为空,get会在原地等待队列中有数据过来
二 、基于队列实现进程间通信
from multiprocessing import Queue,Process
def producer(q):
q.put('hello baby!')
def consumer(q):
print(q.get())
if __name__ == '__main__':
q = Queue() # 生成一个队列对象
p1 = Process(target=producer,args=(q,))
c1 = Process(target=consumer,args=(q,))
p1.start()
c1.start()
三 、 生产者消费者模型(重点)
"""
生产者:做包子的 生产数据的
消费者:买包子的 处理数据的
解决供需不平衡的问题
定义一个队列,用来存放固定数量的数据
解决一个生产者和消费者不需直接打交道,两者都通过队列实现数据传输
Queue:管道+锁
"""
from multiprocessing import Queue,Process,JoinableQueue
import time
import random
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()
if data is None:break
time.sleep(random.randint(1, 3))
print('%s吃了%s'%(name,data))
q.task_done() # 告诉你的队列,你已经将数据取出并且处理完毕
if __name__ == '__main__':
q = JoinableQueue() # 生成一个队列对象
p1 = Process(target=producer,args=('大厨egon','包子',q))
p2 = Process(target=producer,args=('靓仔tank','生蚝',q))
c1 = Process(target=consumer,args=('吃货owen',q))
c2 = Process(target=consumer,args=('坑货kevin',q))
p1.start()
p2.start()
c1.daemon = True
c2.daemon = True
c1.start()
c2.start()
# 等待生产者生产完所有的数据
p1.join()
p2.join()
# 在生产者生产完数据之后,往队列里面放一个提示性的消息,告诉消费者已经没有数据,你走吧,不要等了
# q.put(None)
# q.put(None)
q.join() # 等待队列中数据全部取出
print('主')
线程
1 、什么是线程?
进程:资源单位
线程:执行单位
注意:每一个进程中都会自带一个线程
2 、为什么要有线程
开一个进程:
申请一个内存空间 耗时
将代码拷贝到申请的内存空间中 耗时
开线程:
不需要申请内存空间
开线程的开销远远小于开进程的开销!
3 、如何使用线程:几乎和进程一毛一样
一 、开启线程的两种方式
方式一:
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=('egon',))
t.start() # 开启线程的速度非常快,几乎代码执行完线程就已经开启
print('主')
方式二:
from threading import Thread
import time
class MyThread(Thread):
def __init__(self,name):
super().__init__()
self.name = name
def run(self):
print('%s is running' % self.name)
time.sleep(1)
print('%s is over'%self.name)
if __name__ == '__main__':
t = MyThread('jason')
t.start()
print('主')
二 、线程之间数据共享
from threading import Thread
x = 100
def task():
global x
x = 666
t = Thread(target=task)
t.start()
t.join()
print(x)
-->> 1
三 、 线程互斥锁
from threading import Thread,Lock
import time
mutex = Lock()
n = 100
def task():
global n
mutex.acquire() #加锁
tmp = n
time.sleep(0.1)
n = tmp -1
mutex.release() #释放
t_list = []
for i in range(100):
t = Thread(target=task)
t.start()
t_list.append(t)
for t in t_list:
t.join()
print(n)
四 、 线程对象的其他属性和方法
from threading import Thread,active_count,current_thread
import os
import time
def task(name):
# print('%s is running'%name,os.getpid())
print('%s is running'%name,current_thread().name,current_thread().getName())
time.sleep(1)
print('%s is over'%name)
def info(name):
print('%s is running' % name, current_thread().name, current_thread().getName())
time.sleep(1)
print('%s is over' % name)
t = Thread(target=task,args=('关磊',))
t1 = Thread(target=info,args=('关超',))
t.start()
t1.start()
t.join()
print(active_count()) # 当前存活的线程数
print(os.getpid())
print(current_thread().name)
print(current_thread().getName())
五 、 守护线程
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=('王磊',))
# t.daemon = True
t.start()
print('主')