python基础(21)-线程通信

python基础(21)-线程通信,第1张

到这里,我们要聊一下线程通信的内容;

首先,我们抛开语言不谈,先看看比较基础的东西,线程间通信的方式;其实也就是哪几种(我这里说的,是我的所谓的知道的。。。)事件,消息队列,信号量,条件变量(锁算不算?我只是认为是同步的一种);所以我们也就是要把这些掌握了,因为各有各的好处嘛;

条件变量我放到了上面的线程同步里面讲了,我总感觉这算是同步的一种,没有很多具体信息的沟通;同时吧,我认为条件变量比较重要,因为这种可以应用于线程池的 *** 作上;所以比较重要;这里,抛开条件变量不谈,我们看看其他的东西;

1、消息队列:

queue 模块下提供了几个阻塞队列,这些队列主要用于实现线程通信。在 queue 模块下主要提供了三个类,分别代表三种队列,它们的主要区别就在于进队列、出队列的不同。

关于这三个队列类的简单介绍如下:

queueQueue(maxsize=0):代表 FIFO(先进先出)的常规队列,maxsize 可以限制队列的大小。如果队列的大小达到队列的上限,就会加锁,再次加入元素时就会被阻塞,直到队列中的元素被消费。如果将 maxsize 设置为 0 或负数,则该队列的大小就是无限制的。

queueLifoQueue(maxsize=0):代表 LIFO(后进先出)的队列,与 Queue 的区别就是出队列的顺序不同。

PriorityQueue(maxsize=0):代表优先级队列,优先级最小的元素先出队列。

这三个队列类的属性和方法基本相同, 它们都提供了如下属性和方法:

Queueqsize():返回队列的实际大小,也就是该队列中包含几个元素。

Queueempty():判断队列是否为空。

Queuefull():判断队列是否已满。

Queueput(item, block=True, timeout=None):向队列中放入元素。如果队列己满,且 block 参数为 True(阻塞),当前线程被阻塞,timeout 指定阻塞时间,如果将 timeout 设置为 None,则代表一直阻塞,直到该队列的元素被消费;如果队列己满,且 block 参数为 False(不阻塞),则直接引发 queueFULL 异常。

Queueput_nowait(item):向队列中放入元素,不阻塞。相当于在上一个方法中将 block 参数设置为 False。

Queueget(item, block=True, timeout=None):从队列中取出元素(消费元素)。如果队列已满,且 block 参数为 True(阻塞),当前线程被阻塞,timeout 指定阻塞时间,如果将 timeout 设置为 None,则代表一直阻塞,直到有元素被放入队列中; 如果队列己空,且 block 参数为 False(不阻塞),则直接引发 queueEMPTY 异常。

Queueget_nowait(item):从队列中取出元素,不阻塞。相当于在上一个方法中将 block 参数设置为 False。

其实我们想想,这个队列,是python进行封装的,那么我们可以用在线程间的通信;同时也是可以用做一个数据结构;先进先出就是队列,后进先出就是栈;我们用这个栈写个十进制转二进制的例子:

没毛病,可以正常的打印;其中需要注意的就是,maxsize在初始化的时候如果是0或者是个负数的话,那么就会是不限制大小;

那么其实我们想想,我们如果用做线程通信的话,我们两个线程,可以把队列设置为1的大小,如果是1对多,比如是创建者和消费者的关系,我们完全可以作为消息队列,比如说创建者一直在创建一些东西,然后放入到消息队列里面,然后供消费着使用;就是一个很好的例子;所以,其实说是消息队列,也就是队列,没差;

=====================================================================

下面来看一下事件

Event 是一种非常简单的线程通信机制,一个线程发出一个 Event,另一个线程可通过该 Event 被触发。

Event 本身管理一个内部旗标,程序可以通过 Event 的 set() 方法将该旗标设置为 True,也可以调用 clear() 方法将该旗标设置为 False。程序可以调用 wait() 方法来阻塞当前线程,直到 Event 的内部旗标被设置为 True。

Event 提供了如下方法:

is_set():该方法返回 Event 的内部旗标是否为True。

set():该方法将会把 Event 的内部旗标设置为 True,并唤醒所有处于等待状态的线程。

clear():该方法将 Event 的内部旗标设置为 False,通常接下来会调用 wait() 方法来阻塞当前线程。

wait(timeout=None):该方法会阻塞当前线程。

这里我想解释一下;其实对于事件来说,事件可以看成和条件变量是一样的,只是我们说说不一样的地方;

1、对于事件来说,一旦触发了事件,也就是说,一旦set为true了,那么就会一直为true,需要clear调内部的标志,才能继续wait;但是conditon不是,他是一次性的唤醒其他线程;

2、conditon自己带锁;事件呢?不是的;没有自己的锁;比如说有一个存钱的线程,有一个是取钱的线程;那么存钱的线程要存钱;需要怎么办呢?1、发现银行没有钱了(is_set判断);2、锁住银行;3、存钱;4、释放银行;5、唤醒事件;对于取钱的人;1、判断是否有钱;2、被唤醒了,然后锁住银行;3、开始取钱;4、清理告诉存钱的人,我没钱了(clear);5、释放锁;6、等着钱存进去;

其实说白了,就是记住一点;这个旗标需要自己clear就对了

写个例子,怕以后忘了怎么用;

其实时间和信号量比较像;但是信号量不用自己清除标志位;但是事件是需要的;

512 把列表当作队列使用

你也可以把列表当作队列使用,队列作为特定的数据结构,最先进入的元素最先释放(先进先出)。不过,列表这样用效率不高。相对来说从列表末尾添加和d出很快;在头部插入和d出很慢(因为,为了一个元素,要移动整个列表中的所有元素)。

要实现队列,使用 collectionsdeque,它为在首尾两端快速插入和删除而设计。例如:

>>> from collections import deque

>>> queue = deque(["Eric", "John", "Michael"])

>>> queueappend("Terry") # Terry arrives

>>> queueappend("Graham") # Graham arrives

>>> queuepopleft() # The first to arrive now leaves

'Eric'

>>> queuepopleft() # The second to arrive now leaves

'John'

>>> queue # Remaining queue in order of arrival

deque(['Michael', 'Terry', 'Graham'])

可以考虑把顾客作为一个类,类有属性:顾客序号、进入时间、等待时间、离开时间、理发师序号。

每个顾客作为一个对象,把所有对象放在一个队列或者数组里。

按照一个小时三个顾客的规则处理队列中的对象,直到全部处理完。

最后根据队列处理结果,打印输出。

class customer:

    def __init__(self, cid, itime):

        selfcid = cid

        selfitime = itime

        selfwtime = 0

        selfltime = 0

        selfotime = 0

        selfopid  = -2

    def wait(self):

        selfwtime += 1

        if wtime == 3:

            selfop = -1

            selfltime = selfitime + wtime

    def op(self, opid):

        selfopid = opid

        selfotime= selfitime + selfwtime

        selfltime= selfitime + selfwtime + 1

    

    def print(self):

        print(selfcid,

        selfitime, selfwtime, selfltime, selfotime, selfopid)

if __name__ == '__main__':

    ctable = [[9,1],[10,2],[11,4],[12,3],[13,6],[14,2],[15,3],[16,4],[17,5],[18,7],[19,10],[20,8],[21,3],[22,1]]

    clist = []

    cid = 0

    #初始化顾客队列

    for i,j in ctable:

        for op in range(j):

            clistappend(customer(cid, i))

            cid += 1

    #按小时依次处理

    opid = 0

    for i in range(9, 24):

        #处理的过程这里略

    #打印结果

    for c in clist:

        cprint()

水平有限,不会造轮子,只为学习。

在原来写端口扫描的基础上进一步爬取web服务的title信息,方便收集信息。

适用于在外网收集资产形成IP字典后去批量获取title,意在最快地寻找脆弱点。

自行安装BeautifulSoup4、requests库。

V10

python3 写的单线程爬取web系统的title信息。

注解

1使用BeautifulSoup4库来解析HTML,爬取title信息;

2打印title时,带有颜色的输出;

3在开放443、4433、8443端口时,采用>

python使用websocket发送queue。

Python需要主动向前端Vue 工程推送消息,搭建websocket服务以后,编写简单的代码,可以发数据,实际的数据是需要python从rabbitMQ里面获取数据,也就是websocket实时获取队列的数据,在整个项目中:

☆ ☝️main方法,启动一个线程池

☆ 创建队列queue,然后从队列里面获取数据

⭐️ 与MQ创建连接,直接消费MQ数据

要回答这个问题我们首先看看在流水线上的案列,如果人的速度很慢,机器的速度比人的速度快很多,就会造成,机器生产的东西没有及时处理,越积越多,造成阻塞,影响生产。

打个比方如果出现人的速度跟不上机器速度怎么办,这个时候我们就需要第三方,监管人员(任务队列)把机器生产的东西,放在一个地方,(队列),然后分配给每个用户,有条不理的执行。

消息队列

消息队列的输入是工作的一个单元,称为任务,独立的职程(Worker)进程持续监视队列中是否有需要处理的新任务。

Celery 用消息通信,通常使用中间人(Broker)在客户端和职程间斡旋。这个过程从客户端向队列添加消息开始,之后中间人把消息派送给职程,职程对消息进行处理。如下图所示:

环境

任务脚本

flower github

在234 上flowerpy 的脚本

以上就是关于python基础(21)-线程通信全部的内容,包括:python基础(21)-线程通信、python 把列表当作队列使用方法、用python写,给个思路等相关内容解答,如果想了解更多相关内容,可以关注我们,你们的支持是我们更新的动力!

欢迎分享,转载请注明来源:内存溢出

原文地址:https://54852.com/web/9442918.html

(0)
打赏 微信扫一扫微信扫一扫 支付宝扫一扫支付宝扫一扫
上一篇 2023-04-28
下一篇2023-04-28

发表评论

登录后才能评论

评论列表(0条)

    保存