码迷,mamicode.com
首页 > 编程语言 > 详细

线程、进程、协程和GIL(三)

时间:2019-01-13 01:56:03      阅读:197      评论:0      收藏:0      [点我收藏+]

标签:启动   tar   队列   name   http   lan   信号量   线程间通信   生产者消费者   

上一篇文章介绍了:创建县城的两种方式、Event对象判断线程是否启动、利用信号量控制线程并发。

博客链接:线程、进程、协程和GIL(二)

这一篇来说说线程间通信的那些事儿: 

  一个线程向另一个线程发送数据最安全的方式就是使用queue库中的队列了,通过创建一个供多个线程共享的Queue对象,这些线程使用put()和get()操作来向队列中添加数据或者从队列中取出数据,以达到线程间通信的效果。

  queue队列基本方法:

    queue.Queue(maxsize = num):  FIFO  先进先出队列,如果maxsize小于或等于0 则代表队列长度无线。

    queue.LifoQueue(maxsize = num): LIFO 后进先出队列(类似于栈),如果maxsize小于或等于0 则代表队列长度无线。

    Queue.qsize(): 返回当前队列中元素的个数

         Queue.empty()   如果队列为空,返回True,反之False 

         Queue.full()   如果队列满了,返回True,反之False

         Queue.get([block[, timeout]])   读队列,timeout等待时间 

         Queue.put(item, [block[, timeout]])   写队列,timeout等待时间 

         Queue.queue.clear()   清空队列

  使用Queue构造生产者消费者模型来实现线程间的通信:

import time
from queue import Queue,LifoQueue
from threading import Thread

def producer(in_q):
    while True:
        time.sleep(1)
        data = 包子
        if in_q.full() == True:
            print(蒸笼满了,放不下了)
        in_q.put(data)  # 向队列中塞东西
        print(小明蒸%s! %(data))

def customer(out_q):
    while True:
        time.sleep(3)
        if out_q.empty() == True:
                print(小红没取到包子,饿死了!)
        data = out_q.get() # 从队列中取东西
        print(小红取 %s  % (data))

if __name__ == __main__:
    q = Queue(maxsize=3)
    t1 = Thread(target=producer, args=(q,))
    t2 = Thread(target=customer, args=(q,))
    t1.start()
    t2.start()

  上面的代码实现了一个简单的生产者消费者,小明负责蒸包子,小红负责吃包子。当队列被包子塞满时,小明就再也放不进去了,此时生产者这个线程就会阻塞。当小红将队列中的包子吃完时,消费者这个线程就会阻塞。因为Queue对象已经封装了必要的锁,所以我们可以在多个线程之间安全的功能共享数据。

  但是在生产者消费者的关闭问题会有一些麻烦,通用的解决方式就是在队列中放置一个特殊值,当消费者读到这个值时,就终止执行:

 

 

线程、进程、协程和GIL(三)

标签:启动   tar   队列   name   http   lan   信号量   线程间通信   生产者消费者   

原文地址:https://www.cnblogs.com/ss-py/p/10252797.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!