zoukankan      html  css  js  c++  java
  • 12.2、多线程通信:queue

    queue:

    • 什么是队列:是一种特殊的结构,类似于列表。不过就像排队一样,队列中的元素一旦取出,那么就会从队列中删除。
    • 线程之间的通信可以使用队列queue来进行
    • 线程如何使用queue.Queue【还有其他类型的对象下面讲】来通信:
      • 1.创建一个Queue对象:对象=queue.Queue(x),x是队列容量,x可以不填,默认没有容量限制,    
      • 2.get()可以使线程从队列中获取一个元素,如果队列为空,get会等待,get可以设置timeout参数,这是等待时间
      • 3.put()可以往队列中放入一个元素【默认队列Queue是先入先出的,先放入的元素会先取出去】,如果队列满了,put会等待,put可以设置timeout参数,这是等待时间
      • image

    【下例为:sender线程发送直径给recvder线程,recvder计算得出周长】

    import threading,time,queue,random
    def sender():#sender发送直径
        while True:
            x=random.randint(1,10)
            print("send done:",x)
            q.put(x)#每个一秒就放入一个随机数
            time.sleep(1)#每隔一秒就放入一个a
    
    def recvder():#recvder计算周长
       while True:
           x=q.get()
           print("recv done:",x*3.14)#每隔一秒就取出一个元素,计算结果
           time.sleep(1)
    
    q=queue.Queue()
    t1=threading.Thread(target=sender)
    t2=threading.Thread(target=recvder)
    
    t1.start()
    t2.start()
    
    t1.join()
    t2.join()
    • Queue 对象已经包含了必要的锁,所以不用担心会出错
    import threading,time,queue,random
    def sender():#sender发送直径
        while True:
            x=random.randint(1,10)
            print("send done:",x)
            q.put(x)#每个一秒就放入一个随机数
            time.sleep(1)#每隔一秒就放入一个a
    
    def recvder():#recvder计算周长
       while True:
           x=q.get()
           print(threading.current_thread(),"recv done:",x*3.14)#每隔一秒就取出一个元素,计算结果
           time.sleep(2)
    
    
    q=queue.Queue()
    t1=threading.Thread(target=sender)
    t2=threading.Thread(target=recvder)
    t3=threading.Thread(target=recvder)
    
    t1.start()
    t2.start()
    t3.start()
    
    t1.join()
    t2.join()
    t3.join()

    注:

    队列可以有容量限制:

    image

    timeout的设置:

    image


    队列的其他相关函数【设q为一个Queue对象】:

    • q.qsize():返回当前队列的元素个数
    • q.empty():判断队列是否空,返回布尔值
    • q.full():判断队列是否满,返回布尔值
    • q.get_nowait():直接使用get(),如果此时队列中没有元素,那么会阻塞等待,使用get_nowait()后,如果队列中没有元素,那么会报错
    • q.put_nowait():直接使用put(),如果此时队列满了,那么会阻塞等待,使用put_nowait()后,如果队列已经满了,那么会报错

     

    • q.task_done() :在完成一项工作之后,task_done()函数向任务已经完成的队列发送一个信号【功能类似于:有一个只能承重一个人的独木桥,A来了发现B在桥上,所以A不能上桥,他就在等,等到B过完桥后喊一下他,他才知道B过完桥了】【q.task_done主要是跟q.join()配合使用的】
    • q.join():实际上意味着等到队列为空,再执行别的操作【每次get后需要调用task_done,直到所有队列为空,这时才会执行join下面的】
    import threading,queue,time
    """
    这个例子是:厂家跟司机约定,生产满3个,司机才来拉,
    而一个个拉走,只有当3个都拉走,厂家才继续生产
    """
    def producer():#厂家
        while True:
            for i in range(3):
                q.put(i)
            start_time=time.time()
            q.join()##结果显示join这里堵塞住了厂家线程
            print("wait time:",time.time()-start_time)#用来测试是否堵塞,证明不是因为司机的sleep堵塞运行
    
    
    def driver():#老司机
        while True:
            for i in range(3):
                print(q.get())
                q.task_done()
            print("")
            time.sleep(2)
    
    
    q=queue.Queue()
    t1=threading.Thread(target=producer)
    t2=threading.Thread(target=driver)
    
    t1.start()
    t2.start()
    
    t1.join()
    t2.join()

    image


    queue中除了Queue之外,还有其他的队列,下面是常用的几个:

    • Queue是先入先出的队列:

    image

    • LifoQueue则是后入先出的队列

    image

    • PriorityQueue是由装入元素时指定的优先级来决定出元素的顺序的:
      • 创建方法:队列对象=queue.PriorityQueue()
      • 优先级是小的优先,但不能混合排序,str的只能跟str的一起排序,int的只能跟int一起排序
      • PriorityQueue的put的参数是元组,格式为:队列对象.put((优先级, 数据))

    imageimage

    • deque 是双端队列,允许先入先出和后入后出,即两端都可以出

  • 相关阅读:
    Ubuntu 14.04 卸载通过源码安装的库
    Ubuntu 14.04 indigo 相关依赖
    Ubuntu 14.04 indigo 安装 cartographer 1.0.0
    Ubuntu 14.04 改变文件或者文件夹的拥有者
    安装cartographer遇到Unrecognized syntax identifier "proto3". This parser only recognizes "proto2"问题
    Unrecognized syntax identifier "proto3". This parser only recognizes "proto2". ”问题解决方法
    查看所有用户组,用户名
    1卸载ROS
    Ubuntu14.04 软件安装卸载
    Ubuntu14.04系统显示器不自动休眠修改
  • 原文地址:https://www.cnblogs.com/progor/p/8436559.html
Copyright © 2011-2022 走看看