Python35 events(事件)、队列

事件(events)

基于event实现绿灯举例的多线程 程序

def lighter():
    count = 0
    event.set()
    ##先设置标志位为真,表示初始状态就是绿灯。否则当下面的if count > 5之前,标志位都是没有被设置的
    while True:
        if count > 5 and count <10: #大于5并且小于10就改成红灯
            # 这里代码不能只写成if count > 5,因为只要满足大于5,就不会去匹配大于10的elif条件了。
            event.clear()   #把标志位清空,检查标志位,如果标志位没有被设置,则当做红灯。
            print ("\033[41;1m red light is on...\033[0m")
            ## 这里>5 and <10的数是6-9,所以这里会打印红灯4次。
        elif count > 10:    #红灯到绿灯期间设置时间为10秒,当大于30时,设置标志位
            event.set() #设置标志位,检查到这个标志位,就当做已经绿灯
            count = 0   #用count来计数多少秒,当设置为绿灯时就清空为0秒,20秒后就红灯
        else:
            print("\033[42;1m green light is on...\033[0m")
            ## 匹配count既不大于5,也不大于10时(也就是小于5时),打印绿灯亮
            ## 这里0-5会打印绿灯6次。

        time.sleep(1)   #设置每一秒循环一次,这样20秒后就红灯,20秒到30秒后就变成绿灯。
        count += 1

def car(name):
    while True:
        if event.is_set():  #这里判断如果事件设置了标志位(表示绿灯)
            print ("[%s] running..." %name)
            time.sleep(1)
        else:   #标志位为空表示红灯
            print ("[%s] sees red light, waiting......" %name)
            event.wait()    #如果判断标志位为空,则阻塞程序,直到标志位为真。
            print ("[%s] green light is on, start going... "%name)

light = threading.Thread(target=lighter,)
light.start()

car1 = threading.Thread(target=car,args=("car1",))
car1.start()

执行结果:

可以看到绿灯时,车就正常行驶; 红灯时就等待。


队列(queue)

FIFO(先进先出)

队列的作用:
1、解耦:避免两者之间的过度依赖,以免其中一方出现问题,另一方不能再执行。
2、效率:增加数据处理的效率。

队列可以理解为一个容器,用来放数据的,不过这个容器中的数据是有顺序的。


import queue

q = queue.Queue()   #先生成一个队列对象
q.put("d1") #将d1这个数据放入队列中
q.put("d2") #将d2这个数据也放入队列中
q.put("d3")

q.qsize()   # 来查询当前队列数据数量

print (q.get()) #这里不能取出指定的数据,只能根据先进先出的顺序来取出数据,所以这里取出的是"d1"这个数据
print (q.get()) #这里取出的是"d2"这个数据
print (q.get()) #这里取出的是"d3"这个数据

执行结果:
d1
d2
d3
## 先进先出的顺序来get数据

10办公


import queue

q = queue.Queue()
q.put("d1")
q.put("d2")
q.put("d3")

q.qsize()   

print (q.get())
print (q.get())
print (q.get()) 

print (q.get())
## 之前只进入了3个数据,且3个数据也被取出了,此时数据为空,我再次取数据就会卡在这,因为没有数据了,会一直卡在这等待新的数据进来

执行结果:


可以看到程序卡主了。


import queue

q = queue.Queue()
q.put("d1")
q.put("d2")
q.put("d3")

q.qsize()

print (q.get())
print (q.get())
print (q.get())

print (q.get(block=False))
## 默认就存在block=True这个参数,True的话表示如果数据为空就卡主,设置False就不卡主


不在卡主,并且抛出异常

import queue

q = queue.Queue()
q.put("d1")
q.put("d2")
q.put("d3")

q.qsize()

print (q.get())
print (q.get())
print (q.get())

print (q.get(timeout=3))
## 设置如果卡主的话,卡多久,这里设置为卡3秒


卡3秒后,依然没有数据进来,会抛出异常。


import queue

q = queue.Queue()
q.put("d1")
q.put("d2")
q.put("d3")

q.qsize()

print (q.get())
print (q.get())
print (q.get())

print (q.get_nowait())
## 使用get_nowait()来取数据,如果取的数据是空就会抛出异常。


可以使用try,except异常来使用get_nowait()来解决获取空数据的问题;
也可以使用if q.qsize()来判断==0的话,就是空数据,然后在做下一步操作。


import queue

q = queue.Queue(maxsize=3)  ## 设置队列中最多可以有多少个数据
q.put("d1")
q.put("d2")
q.put("d3")
q.put("d4") ##因为设置最有能有3个数据,当我们设置第4个数据的时候前三个数据还没有取出,就会卡主
##可以设置多个线程,变放变取数据,就不会卡主了。

import queue

q = queue.Queue(maxsize=3)
q.put("d1")
q.put("d2")
q.put("d3")
q.put("d4",block=False,timeout=3)
## put也支持block和timeout

Lifo (last in first out 后进先出)

一般场景都是先入先出,后入先出的情况比较少。
卖水果就可以实现后入先出的场景,因为后来的水果比较新鲜,所以就先卖出去的快。

import queue

q = queue.LifoQueue()
q.put(1)
q.put(2)
q.put(3)

print (q.get())
print (q.get())
print (q.get())

执行结果:
3
2
1

PriorityQueue(优先级队列)

存储数据时可以设置优先级队列


import queue

q = queue.PriorityQueue()
q.put((10,"Amy"))
q.put((-1,"Peter"))
q.put((3,"Zhangsan"))
q.put((6,"lisi"))

print (q.get())
print (q.get())
print (q.get())
print (q.get())

执行结果:
(-1, ‘Peter‘)   #优先级最高
(3, ‘Zhangsan‘)
(6, ‘lisi‘)
(10, ‘Amy‘)     #优先级最低
##将数字放在前面就按照数字越小,越优先出
## 也可以按照字母等顺序来排列。

生产者消费者模型

假如生产者是视频服务器,消费者是用户,用户消费(看视频),将请求转到后台服务器,生产者处理、提供视频数据。
但是消费者并不关心你后台提供了多少台服务器,所以这种模型解耦比较好。

import threading,time
import queue

q = queue.Queue()

def Producer(name):
    for i in range(10):
        q.put("骨头%s"%i) ##生产10个骨头

def Consumer(name):
    while q.qsize() > 0:    #判断队列还有数据就循环
        print ("[%s]取到[%s]并且吃了它..."%(name,q.get())) #消费骨头

p = threading.Thread(target=Producer,args=("LiSi",))
c = threading.Thread(target=Consumer,args=("Dog",))

p.start()
c.start()

执行结果:
[Dog]取到[骨头0]并且吃了它...
[Dog]取到[骨头1]并且吃了它...
[Dog]取到[骨头2]并且吃了它...
[Dog]取到[骨头3]并且吃了它...
[Dog]取到[骨头4]并且吃了它...
[Dog]取到[骨头5]并且吃了它...
[Dog]取到[骨头6]并且吃了它...
[Dog]取到[骨头7]并且吃了它...
[Dog]取到[骨头8]并且吃了它...
[Dog]取到[骨头9]并且吃了它...
## 生产了10个骨头,都被dog给吃了。

import threading,time
import queue

q = queue.Queue(maxsize=10) #最大放入十个骨头

def Producer(name):
    count = 1
    while True: #为了持续性的生产骨头,这里使用while。
            q.put("骨头%s"%count) ##当骨头超过10个的时候,就卡主了,直到骨头被取出少于10时循环放骨头进来
            print ("生产了骨头%s"%count)
            count += 1
            time.sleep(2)   #两秒生产1个

def Consumer(name):
    while True:    #这里设置True,而不是>0,因为刚生产1个被吃掉的话,就不大于0了,dogs就不会再吃骨头
        print ("[%s]取到[%s]并且吃了它..."%(name,q.get()))
        time.sleep(1)   #这里设置每秒吃1个骨头但是因为生产的慢(2秒生产1个),所以就吃的慢。

p = threading.Thread(target=Producer,args=("LiSi",))
c1 = threading.Thread(target=Consumer,args=("Dog1",))
c2 = threading.Thread(target=Consumer,args=("Dog2",))

p.start()
c1.start()
c2.start()

执行结果:
生产了骨头1
[Dog1]取到[骨头1]并且吃了它...
生产了骨头2
[Dog2]取到[骨头2]并且吃了它...
生产了骨头3
[Dog1]取到[骨头3]并且吃了它...
生产了骨头4
[Dog2]取到[骨头4]并且吃了它...
生产了骨头5
[Dog1]取到[骨头5]并且吃了它...
生产了骨头6
[Dog2]取到[骨头6]并且吃了它...
........

def Producer(name):
    count = 1
    while True:
            q.put("骨头%s"%count)
            print ("生产了骨头%s"%count)
            count += 1
            time.sleep(0.5)   #现在0.5秒生产1个,相当于1秒生产2个

def Consumer(name):
    while True:
        print ("[%s]取到[%s]并且吃了它..."%(name,q.get()))
        time.sleep(1)
        ##因为生产的快,两个线程就吃的快(每个线程每隔1秒吃一个)
        ##两个线程相当于1秒能吃2个,刚好与生产速度持平;
        ##如果生产过快的话,就是生产大于消费的速度了。

p = threading.Thread(target=Producer,args=("LiSi",))
c1 = threading.Thread(target=Consumer,args=("Dog1",))
c2 = threading.Thread(target=Consumer,args=("Dog2",))

p.start()
c1.start()
c2.start()

执行结果:
生产了骨头1
[Dog1]取到[骨头1]并且吃了它...
生产了骨头2
[Dog2]取到[骨头2]并且吃了它...
生产了骨头3
[Dog1]取到[骨头3]并且吃了它...
生产了骨头4
[Dog2]取到[骨头4]并且吃了它...
生产了骨头5
[Dog1]取到[骨头5]并且吃了它...

## 生产者消费者模型解决了解耦(生产和消费各干各的)、排队的问题(只要生产的资源够,消费者不需要排队)。

原文地址:http://blog.51cto.com/daimalaobing/2087352

时间: 2024-10-10 17:03:25

Python35 events(事件)、队列的相关文章

ActiveX控件的Events事件

http://labview360.com/article/info.asp?TID=10152&FID=165 Active X函式库 对使用LabVIEW作为开发环境的开发人员来说,如果能呼叫或引用其他程式所开发的物件如:OCX.DLL…等.不仅能够缩短开发时间,更能随心所欲的设计出所需要的功能.毕竟在LabVIEW的开发环境下或多或少还是会有所限制,例如:如何用LabVIEW制作常注程式,也就是将程式放到System Tray上呢?LabVIEW为了解决这样的问题,针对Active X物件

基础入门_Python-模块和包.Gevent事件/队列/组/池/信号量/子进程?

常用结构: 1.Event类,事件主要用于Greenlet之间的异步通信 e = gevent.event.Event() -> Event 说明: 创建一个信号对象 e.set() -> None 说明: 设置标志位 e.clear() -> None 说明: 清除标志位 e.wait() -> None 说明: 阻塞直至标志位被设置 #!/usr/bin/env python # -*- coding: utf-8 -*- """ # # Auth

python 并发编程 锁 / 信号量 / 事件 / 队列(进程间通信(IPC)) /生产者消费者模式

(1)锁:进程之间数据不共享,但是共享同一套文件系统,所以访问同一个文件,或同一个打印终端,是没有问题的,而共享带来的是竞争,竞争带来的结果就是错乱,如何控制,就是加锁处理. 虽然使用加锁的形式实现了顺序的执行,但是程序又重新变成串行了,这样确实会浪费了时间,却保证了数据的安全. (Lock) import json from multiprocessing import Process,Lock ###### 锁 ###### import time import random def get

协程,事件,队列,同步,异步,回调函数

协程 什么是协成?单个线程并发的处理多个任务,程序控制协成的切换+保持状态,协成的切换速度非常快,蒙蔽了操作系统的眼睛,让操作系统认为CPU一直在运行 进程或线程都是由操作系统控制CPU来回切换,遇到阻塞就切换执行其他任务,协成是程序控制的,霸占CPU执行任务,会在操作系统控制CPU之前来回切换,操作系统就认为CPU一直在运作 协程的优点: 1.开销小 2.运行速度快 3.协程会长期霸占CPU只执行我程序里的所有任务 协程的缺点: 1.协程属于微并发,处理任务不易过多 2.协程的本质是单线程,无

Backbone事件Events

说道Backbone的事件机制.自己也是逗逼了.敲了一遍Backbone的源码..居然是还不知道他的机制.. 先上Events On对象的源码 /** * Created by More on 2015/11/28. */var Events = Backbone.Events ={ /** * params: * events : 事件们 * callback : 回调函数 * context : 上下文,俗称的this * * **/ on: function(events,callback

openwrt gstreamer实例学习笔记(七. gstreamer 缓冲区(Buffers)和事件(Events))

1)概述 管道的数据流由一组缓冲区和事件组成,缓冲区包括实际的管道数据,事件包括控制信息,如寻找信息和流的终止信号.所有这些数据流在运行的时候自动的流过管道. 2) 缓冲区(Buffers) 缓冲区包含了你创建的管道里的数据流.通常一个source element会创建一个新的缓冲区,同时element还将会把缓冲区的数据传递给下一个element.当使用GStreamer底层构造来创建一个媒体管道的时候,你不需要自己来处理缓冲区,element将会为你处理这些缓冲区. 一个缓冲区主要由以下一个

Reactor事件模型在Redis中的应用

1 模型简介 Redis没有使用第三方的libevent等网络库,而是自己开发了一个单线程的Reactor模型的事件处理模型.而Memcached内部使用的libevent库,多线程模型. 综合对比可见:nginx,memcached,redis网络模型总结 Redis在主循环中统一处理文件事件和时间事件,信号事件则由专门的handler来处理. 文件事件,我理解为IO事件,Redis将产生事件套接字放入一个就绪队列中,即redisServer.aeEventLoop.fired数组,然后在ae

# 进程/线程/协程 # IO:同步/异步/阻塞/非阻塞 # greenlet gevent # 事件驱动与异步IO # Select\Poll\Epoll异步IO 以及selectors模块 # Python队列/RabbitMQ队列

1 # 进程/线程/协程 2 # IO:同步/异步/阻塞/非阻塞 3 # greenlet gevent 4 # 事件驱动与异步IO 5 # Select\Poll\Epoll异步IO 以及selectors模块 6 # Python队列/RabbitMQ队列 7 8 ############################################################################################## 9 1.什么是进程?进程和程序之间有什么

kubernetes之收集集群的events,监控集群行为

一.概述 线上部署的k8s已经扛过了双11的洗礼,期间先是通过对网络和监控的优化顺利度过了双11并且表现良好.先简单介绍一下我们kubernetes的使用方式: 物理机系统:Ubuntu-16.04(kernel 升级到4.17) kuberneets-version:1.13.2 网络组件:calico(采用的是BGP模式+bgp reflector) kube-proxy:使用的是ipvs模式 监控:prometheus+grafana 日志: fluentd + ES metrics: m