进程之队列(进程之间通信)
队列: 先进先出
堆栈:先进后出
关键字Queue
Queue很后面可以传参数
put:存储数据
get:获取数据
full: 判断队列是否满了
get_nowait: 没有值得的情况下直接报错
empty:判断队列是否被取完
《以上几个方法都不适用于多进程》
实例:
""" from multiprocessing import Queue q = Queue(5) # 括号内部可以传参数,表示这个队列的最大存储数 默认很大 # 往队列中添加值 q.put(1) q.put(2) print(q.full()) # <<<False>>> 列表可以放置五个数据,现在判断是否为满,结果为False q.put(3) q.put(4) q.put(5) print(q.full()) # <<<True>>> 列表已经放满,现在判断结果为True # q.put(6) # 当队列中列队满了之后,再向队列中放置数据是不会报错的,会在原地等待,直到队列中的数据被取走(阻塞状态),当然如果这个时候直接在后面添加取数据一样是会卡在当前 # 取数据get print(q.get()) print(q.get()) print(q.get()) # print(q.get_nowait()) # 现在在还有值的情况不会直接报错 print(q.get()) print(q.get()) # print(q.empty()) #<<<当前还有值所以是False>>> print(q.get_nowait()) #《queue.Empty》在没有值的情况直接报错 # print(q.get()) # 当队列中的数据取完时,再获取值,一样不会报错,依旧会在原地等待
进程之间的通信
队列中子进程和主进程可以相互存取数据
因为进程与进程值间数据是封闭的但是可以使用队列作为一个中间商,在中间为两者互换数据
# from multiprocessing import Process, Queue
"""
def producer(q):
q.put("hello baby~~")
def consumer(q):
print(q.get())
if __name__ == '__main__':
q = Queue()
p = Process(target=producer, args=(q,)) # 创建一个进程
c = Process(target=consumer,args=(q,)) # 创建一个取数据的进程
p.start()
c.start()
# print(q.get())
"""
"""
队列中子进程和主进程可以相互存取数据
因为进程与进程值间数据是封闭的但是可以使用队列作为一个中间商,在中间为两者互换数据
"""
from multiprocessing import Process, Queue, JoinableQueue
import random
import time
# JoinableQueue
# 可共享的队列
def produecer(name, food, q):
for i in range(1,10):
data = "%s生产了%s%s个" % (name, food, i)
time.sleep(random.random())
q.put(data)
print(data)
def cousumer(name,q):
while True:
data = q.get()
if data == None:break
print("%s吃了%s"%(name,data))
time.sleep(random.random())
q.task_done() # 告诉队列你已经在队列里面去了一个数据 并且处理完毕
if __name__ == '__main__':
q = JoinableQueue()
p = Process(target= produecer,args = ("同桌","木糖醇",q))
p2 = Process(target= produecer,args = ("李蕾","口香糖",q))
p3 = Process(target= produecer,args = ("坛坛","羊肉串",q))
c = Process(target=cousumer,args=("吃货猴子",q))
c1 = Process(target=cousumer,args=("八戒",q))
c2 = Process(target=cousumer,args=("空空",q))
p.start()
p2.start()
p3.start()
c.daemon = True # 守护进程
c1.daemon = True # 守护进程
c2.daemon = True # 守护进程
c.start()
c1.start()
c2.start()
p.join()
p2.join()
p3.join()
q.join() # 等待队列数据全部取出
线程:
线程:
什么是线程:
进程和线程都是虚拟单位,都是用来帮助我们形象描述莫种事物
进程:资源单位
线程:执行单位
把内存当做工厂,那么进程就是可以当做工厂里面的车间;
而线程就相当于车间里面的流水线,实际运行的就是线程,而进程其实就是资源
ps:每一个进程都自带了一个线程,这个线程才是真正的执行单位,进程只是在线程运行中提供了相应的的资源
为什么要用线程:
开进程
1.申请内存空间 占用资源
2、“拷贝代码” 占用资源 # 需要吧原来的代码拿过去
开线程:
一个进程里面可以开多个线程,并且线程与线程之间数据是共享的
开启线程的占用资源远远小于开进程的开销
创建线程的两个方法:
一种:
from threading import Thread
import time
def task(name):
print("%s is running" % name)
time.sleep(2)
print("%s is over" % name)
# 开辟进程是不需要使用__main__代码,可以根据习惯写上也可以
p = Thread(target=task, args=("悟空",))
p.start() # 告诉操作系统开辟了一个线程
p.join() # 等待线程结束
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(2)
print("%s is over" % self.name)
t = MyThread("猴子")
t.start()
t.join()
print("主")
线程之间的通信实例(两种方法):
from threading import Thread
age = 18
def task():
global age
age = 17
t = Thread(target=task)
t.start()
t.join()
print(age) # 17 说明子线程可以更改主线程
#第二种方法
age = 19
class MyTread(Thread):
def __init__(self, age):
super().__init__()
self.age = age
def run(self):
print("该更")
t = MyTread(16)
t.start()
print(t.age)
线程对象的其他方法(两种方式):
from threading import Thread, current_thread, active_count
import time
import os
"""
current_thread: 查看当前的线程的主线程(虽然线程和线程之间是没有主次之分)
active_count: 查看当前还在活跃的线程,就是说现在还在存在的
getpid(): 查看线程的id
def task(name, i):
print("%s is running " % name)
print("输出子线程的主线程", current_thread().name)
print("输出子线程的进程id", os.getpid())
time.sleep(2)
print("%s is over" % name)
t = Thread(target=task, args=("旺旺", 1))
t2 = Thread(target=task, args=("旺财", 2))
t.start() # 告诉操作系统开启了一个线程
t2.start() # 告诉操作系统开启了一个线程
t.join() # 主线程等待子线程运行完毕
# t2.join()
print("当前活跃的进程数:", active_count())
print("主")
旺旺 is running
输出子线程的主线程 Thread-1
输出子线程的进程id 11920
旺财 is running
输出子线程的主线程 Thread-2
输出子线程的进程id 11920
旺旺 is over
当前活跃的进程数: 2
主
旺财 is over
"""
class MyThread(Thread):
def __init__(self, name, ):
super().__init__()
self.name = name
def run(self):
print("%s is running " % self.name)
print("输出子线程的主线程", current_thread().name)
print("输出子线程的进程id", os.getpid())
time.sleep(2)
print("%s is over" % self.name)
t = MyThread("temp")
t.start()
t.join()
print("当前活跃的进程数:", active_count())
print("主")
守护线程两种方法:
from threading import Thread, current_thread
import time
"""
主线程的结束也就意味着进程的结束
主线程必须等待其他非守护线程的结束才能结束
(意味子线程在运行的时候需要使用进程中的资源,而主线程一旦结束了资源也就销毁了)
"""
# def task(i):
# print(current_thread().name)
# time.sleep(2)
# print("嘎嘎")
#
#
# t = Thread(target=task, args=(1,))
# t.daemon = True
# t.start()
# print("主")
class MyThread(Thread):
def __init__(self, i):
super().__init__()
self.i = i
def run(self):
print(current_thread().name)
time.sleep(2)
print("嘎嘎")
t = MyThread("1")
t.daemon = True
t.start()
print("主")
线程互斥锁:
from threading import Thread, Lock
import time
n = 100
l = time.time()
def task(mutex):
global n
mutex.acquire() # 获得钥匙
tmp = n
time.sleep(0.1)
n = tmp - 1
mutex.release() # 放开钥匙
t_list = []
mutex = Lock()
for i in range(100):
t = Thread(target=task, args=(mutex,))
t.start()
# t_list.append(t)
# for t in t_list:
t.join()
print(n)
r = time.time()
print(r-l)
线程总结实例:
from threading import Thread
from multiprocessing import Process
import time
def foo():
print(123)
time.sleep(1)
print("end123")
def bar():
print(456)
time.sleep(1)
"""
如果时间和foo的等待时间一样或者更少的情况不会运行end123
相反则运行
"""
print("end456")
if __name__ == '__main__':
t1 = Thread(target=foo)
t2 = Thread(target=bar)
t1.daemon = True
t2.start()
t1.start()
print("!!!!!!!")