python的队列,互斥锁

1.使用类创建子线程demo

​
import time
import threading
class Task(threading.Thread):
    def run(self):
        while True:
            print('11111')
            print(self.name)
            time.sleep(1)
t=Task()
t.start()

while True:
    print('main')
    time.sleep(1)

​

小结

        1.可以自己定义一个类,但是这个类要继承Thread

        2.一定要实现run方法,即要定义一个run方法,并且实现线程需要执行的代码

        3.当调用自己编写的类创建出来的实例对象的run方法,会创建新的线程,并且线程会自动调用run方法

        4.如果出了run方法之外还定义了很多其他的方法,例如xx,那么这些方法需要在run方法中自己去调用线程它不会自动调用

2.并发TCP服务器

import socket

import threading


class HandleData(threading.Thread):
    def __init__(self,client_socket):
        super().__init__()
        self.client_socket=client_socket
    def run(self):
        
        #5.接收/发送数据
        while True:
            recv_content=self.client_socket.recv(1024)
            if len(recv_content) !=0:
                print(recv_content)
                self.client_socket.send(recv_content)
            else:
                self.client_socket.close()
                break

class TCPServer(threading.Thread):
    def __init__(self,port):
        super.__init__()
        self.server_s=None
        #1.创建套接字
        self.server_s=socket.socket(socket.AF_INET,socket.SOCK_STREAM)

        #2.绑定本地信息
        self.seerver_s.bind(('',port))

        #3.将套接字由默认的主动链接模式改为被动模式(监听模块)
        self.server_s.listen(128)
    def run(self):


        while True:
            #4.等待客户端进行链接
            new_s,client_info=self.server_s.accept()
            print(client_info)
            #创建一个新的线程,专门为刚刚链接的客户端服务
            handle_data_thread=HandleData(new_s)
            handle_data_thread.start()

    def __del__(self):
        

        #6.关闭套接字
        self.server_s.close()

tcp_seerver=TCPServer(7788)
tcp_server.start()

3.队列

        3.1队列Queue

import queue
q=queue.Queue()
q.put('11')  #存入字符串
q.put(22) #存入整数
q.put({'num':100}) #存入字典

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

        1.FIFO(first in first out先进先出)

        2.可以存放任意类型数据,例如整数、字符串、字典

        3.使用put放数据

        4.使用get取数据(如果当前队列中没有数据,此时会堵塞)

        3.2堆栈Queue

import queue
q=queue.LifoQueue()
q.put('11')
q.put(22)
q.put({'num':100})

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

        1.LIFO(last in first out后进先出)

        2.可以存放任意类型数据,例如整数、字符串、字典

        3.使用put放数据

        4.使用get取数据(如果当前队列中没有数据,此时会堵塞)

        3.3 优先级Queue

import queue
q=queue.PriorityQueue()
q.put((10,'Q'))
q.put((30,'Z'))
q.put((20,'A'))

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

        1.根据优先级来确定当前要获取的数据

        2.使用put存放

            1.将一个元组放到里面

            2.第1个元素:优先级,数字越小优先级越高

            3.第2个元素是:要存放的数据

        3.使用get来获取(如果当前队列中没有数据,此时会堵塞)

4.带有聊天记录的udp聊天程序

import threading
import socket
import queue
class RecvMsg(threading.Thread):
    def __init__(self,udp_s):
        super.__init__()
        self.udp_s=udp_s
    def run(self):
        while True:
            recv_content,client_info=self.udp_s.recvfrom(1024)
            temp_content='>>>%s(%d):%s'%(client_info[0],client_info[1],recv_content.decode('gbk'))
            print(temp_content)
            self.q.put(temp_content)
    def __del__(self):
        self.upd_s.close()
class SendMsg(threading.Thread):
    def __init__(self,udp_s):
        super.__init__()
        self.udp_s=udp_s
    def run(self):
        while True:
            dest_ip=input('请输入对方的ip:')
            dest_port=int(input('请输入对方的port:'))
                while True:
                    send_content=input('请输入要发送的数据')
                    if send_content:
                        self.udp_s.sendto(send_content.encode('utf-8'),(dest_ip,dest_port))
                        temp_info='<<<%s(%d):%s'%(dest_ip,dest_port,send_content)
                        self.q.put(temp_info)
                    else:
                        break
    def __del__(self):
        self.upd_s.close()
class ChatHistory(threading.Thread):
    def __init__(self,q):
        super().__init__()
        self.q=q

    def run(self):
        while True:
            #从Queue中读取数据
            content=self.q.get()
            #将数据写入到文件
            with open('./chat.txt','a') as f:
                f.write()
                f.write('\n')
    def main():
        #1.创建一个udp套接字
        udp_s=socket.socket(socket.AF_INET,socket.SOCK_DGRAM)
        #2.绑定本地信息
        udp_s.bind('',7890)
        #创建一个FIFO的队列
        
        q=queue.Queue()
        #3.创建一个新的线程对象-目的用来接收数据
        recv_msg_thread=RecvMsg(udp_s,q)
        #4.创建一个新的线程对象-目的用来检测键盘发送数据
        send_msg_thread=SendMsg(udp_s,q)
        #5.创建一个新的线程对象-目的用来存储聊天记录
        chat_history_thread=ChatHistory(q)
        recv_msg_thread.start()
        send_msg_thread.start()
        caht_history_thread.start()

if __name__='__main__':
    main()

5.多线程-共享全局变量

import threading
import time
#1.定义一个全局变量
g_num=0
#2.定义2个函数-用他们来充当线程要执行的代码
def task1():
    global g_num
    g_num=100
    print('task1中,g_num=%d'%g_num)
def task2():
    print('task2中,g_num=%d'%g_num)

#3.创建线程对象
t1=threading.Thread(target=task1)
t2=threading.Thread(target=task2)

#4.调用start创建线程,让线程开始运行
t1.start()
time.sleep(2)  #让主线程延迟一会,保证让task1这个任务先执行完毕
t2.start()

小结

        1.如果一个线程有多个线程,每个线程可以单独执行自己的任务

        2.如果多个线程直接需要数据共享,最简单的方式是,通过全局变量来实现

           1.一个线程修改全局变量

            2.另外一个线程从全局变量中获取数据

通过全局变量可以解决多个线程之间共享数据的问题,但是,如果使用不够恰当,会导致数据错乱

例如有3个线程:

        其中第1、2个修改全局变量,第3个线程获取全局变量的值,可能会出现第1个线程刚刚将数据存放到了全局变量中,本意是想让第3个线程获取它的数据,因为操作系统的调度原因导致了线程3没有被调度,而第2个线程被调度了,恰巧第2个线程也对全局变量进行了修改。当第3个线程去读取数据的时候,读取到的是第2个线程的数据而不是在第1个线程的数据

6.资源竞争的问题

import threading
import time
#1.定义一个全局变量
g_num=0
#2.定义2个函数-用他们来充当线程要执行的代码
def task1(num):

    global g_num
    for i in range(num):
        g_num+=1
    print('task1中,g_num=%d'%g_num)
def task2(num):

    global g_num
    for i in range(num):
        g_num+=1
    print('task2中,g_num=%d'%g_num)

#3.创建线程对象
t1=threading.Thread(target=task1,args=(100,))
t2=threading.Thread(target=task2,args=(100,))

#4.调用start创建线程,让线程开始运行
t1.start()
#time.sleep(2)  #让主线程延迟一会,保证让task1这个任务先执行完毕
t2.start()

g_num+=1应该是一个整体的功能即一气呵成,但是操作系统在执行这个本应该一次性全部执行的代码时,刚执行了一部分,反而去执行其他线程的代码,导致了这样的问题产生

7.互斥锁

import threading
#创建一个互斥锁
mutex=threading.Lock()

#上锁
mutex.acquire()
print('哈哈哈')
mutex.acquire()
#解锁
mutex.release()

如果想要对某些代码一起执行,不想被其他的线程打扰,可以将这些代码放到互斥锁上锁到互斥锁解锁之间

如果这个互斥锁已经被上锁了,那么在这个锁被解开之前,是不能再次上锁的,也就是说:如果这个锁被上锁在解开之前谁要是再次调用acquire对其上锁,那么谁就会被堵塞,直到这个互斥锁被解锁为止

注意:一定是同一把锁才可以

  • 23
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
模拟消息队列,是指在python中通过编程实现一个简单的消息队列的功能。消息队列通常是用于在不同的应用程序或服务之间传递和交换消息的一种方式。 在python中,我们可以使用多线程来模拟消息队列。首先,我们可以定义一个队列(Queue)类,用于存储和管理消息。该类可以包含一些方法,如入队(enqueue)和出队(dequeue)操作。入队操作将消息添加到队列的尾部,出队操作从队列的头部获取并删除消息。 接下来,我们可以创建多个线程,每个线程代表一个应用程序或服务,用于生产和消费消息。生产者线程负责生成消息,并通过调用入队操作将消息添加到队列中;消费者线程则负责从队列中获取消息,并进行处理或响应。 我们可以使用python的threading模块来实现多线程。通过创建并启动生产者和消费者线程,就可以实现模拟消息队列的功能。生产者线程可以使用while循环来生成消息并入队,而消费者线程可以使用while循环来从队列中出队并处理消息。 需要注意的是,在模拟消息队列的过程中,我们还需要考虑线程之间的同步和互斥问题,以保证消息的正确传递和处理。可以使用一些线程同步机制,如互斥(Lock)或条件变量(Condition)来实现线程之间的同步和互斥。 总之,通过使用多线程和一些线程同步机制,我们可以在python中模拟一个简单的消息队列。这个模拟的消息队列可以在不同的应用程序或服务之间传递和交换消息,实现了轻量级的异步通信。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值