Python中使用Queue和Condition进行线程同步的方法

Queue模块保持线程同步
利用Queue对象先进先出的特性,将每个生产者的数据一次存入队列,而每个消费者将依次从队列中取出数据

import threading    # 导入threading模块
import Queue      # 导入Queue模块
class Producer(threading.Thread):# 定义生产者类
  def __init__(self,threadname):
    threading.Thread.__init__(self,name = threadname)
  def run(self):
    global queue  # 声明queue为全局变量
    queue.put(self.getName())  # 调用put方法将线程名添加到队列中
    print self.getName(),'put ',self.getName(),' to queue'
class Consumer(threading.Thread):# 定义消费者类
  def __init__(self,threadname):
    threading.Thread.__init__(self,name = threadname)
  def run(self):
    global queue
    print self.getName(),'get ',queue.get(),'from queue'#调用get方法获取队列中内容
queue = Queue.Queue()  # 生成队列对象
plist = []   # 生成者对象列表
clist = []   # 消费者对象列表
for i in range(10):
  p = Producer('Producer' + str(i))
  plist.append(p)   # 添加到生产者对象列表
for i in range(10):
  c = Consumer('Consumer' + str(i))
  clist.append(c)   # 添加到消费者对象列表
for i in plist:
  i.start()    # 运行生产者线程
  i.join()
for i in clist:
  i.start()    # 运行消费者线程
  i.join()
######运行结果######
>>> Producer0 put Producer0 to queue
Producer1 put Producer1 to queue
Producer2 put Producer2 to queue
Producer3 put Producer3 to queue
Producer4 put Producer4 to queue
Producer5 put Producer5 to queue
Producer6 put Producer6 to queue
Producer7 put Producer7 to queue
Producer8 put Producer8 to queue
Producer9 put Producer9 to queue
Consumer0 get Producer0 from queue
Consumer1 get Producer1 from queue
Consumer2 get Producer2 from queue
Consumer3 get Producer3 from queue
Consumer4 get Producer4 from queue
Consumer5 get Producer5 from queue
Consumer6 get Producer6 from queue
Consumer7 get Producer7 from queue
Consumer8 get Producer8 from queue
Consumer9 get Producer9 from queue

Condition实现复杂的同步
使用Condition对象可以在某些事件触发或者达到特定的条件后才处理数据,Condition除了具有Lock对象的acquire方法和release方法外,
还有wait方法,notify方法,notifyAll方法等用于条件处理。
条件变量保持线程同步:threading.Condition()

  • wait():线程挂起,直到收到一个notify通知才会被唤醒继续运行
  • notify():通知其他线程,那些挂起的线程接到这个通知之后会开始运行
  • notifyAll(): 如果wait状态线程比较多,notifyAll的作用就是通知所有线程(这个一般用得少)
#coding:utf-8

import threading
import time
cond = threading.Condition()
class kongbaige(threading.Thread):
  def __init__(self, cond, diaosiname):
    threading.Thread.__init__(self, name = diaosiname)
    self.cond = cond

  def run(self):
    self.cond.acquire() #获取锁

    print self.getName() + ':一支穿云箭' #空白哥说的第一句话
    self.cond.notify()          #唤醒其他wait状态的线程(通知西米哥 让他说话)
    #然后进入wait线程挂起状态等待notify通知(等西米哥的回复,接下来俩人就开始扯蛋)
    self.cond.wait()

    print self.getName() + ':山无棱,天地合,乃敢与君绝!'
    self.cond.notify()
    self.cond.wait()

    print self.getName() + ':紫薇!!!!(此处图片省略)'
    self.cond.notify()
    self.cond.wait()

    print self.getName() + ':是你'
    self.cond.notify()
    self.cond.wait()

    #这里是空白哥说的最后一段话,接下来就没有对白了
    print self.getName() + ':有钱吗 借点'
    self.cond.notify()       #通知西米哥
    self.cond.release()      #释放锁

class ximige(threading.Thread):
  def __init__(self, cond, diaosiname):
    threading.Thread.__init__(self, name = diaosiname)
    self.cond = cond

  def run(self):
    self.cond.acquire()
    self.cond.wait()  #线程挂起(等西米哥的notify通知)

    print self.getName() +':千军万马来相见'
    self.cond.notify() #说完话了notify空白哥wait的线程
    self.cond.wait()  #线程挂起等待空白哥的notify通知

    print self.getName() + ':海可枯,石可烂,激情永不散!'
    self.cond.notify()
    self.cond.wait()

    print self.getName() + ':尔康!!!(此处图片省略)'
    self.cond.notify()
    self.cond.wait()

    print self.getName() + ':是我'
    self.cond.notify()
    self.cond.wait()

    #这里是最后一段话,后面空白哥没接话了 所以说完就释放锁 结束线程
    print self.getName() + ':滚'
    self.cond.release()

kongbai = kongbaige(cond, '  ')
ximi = ximige(cond, '西米')
#尼玛下面这2个启动标志是关键,虽然是空白哥先开的口,但是不能让他先启动,
#因为他先启动的可能直到发完notify通知了,西米哥才开始启动,
#西米哥启动后会一直处于44行的wait状态,因为空白哥已经发完notify通知了进入wait状态了,
#而西米哥没收到
#造成的结果就是2根线程就一直在那挂起,什么都不干,也不扯蛋了
ximi.start()
kongbai.start()

######运行结果######

  :一支穿云箭
西米:千军万马来相见
  :山无棱,天地合,乃敢与君绝!
西米:海可枯,石可烂,激情永不散!
  :紫薇!!!!(此处图片省略)
西米:尔康!!!(此处图片省略)
  :是你
西米:是我
  :有钱吗 借点
西米:滚
(0)

相关推荐

  • python使用Queue在多个子进程间交换数据的方法

    本文实例讲述了python使用Queue在多个子进程间交换数据的方法.分享给大家供大家参考.具体如下: 这里将Queue作为中间通道进行数据传递,Queue是线程和进程安全的 from multiprocessing import Process, Queue def f(q): q.put([42, None, 'hello']) if __name__ == '__main__': q = Queue() p = Process(target=f, args=(q,)) p.start()

  • Python多进程通信Queue、Pipe、Value、Array实例

    queue和pipe的区别: pipe用来在两个进程间通信.queue用来在多个进程间实现通信. 此两种方法为所有系统多进程通信的基本方法,几乎所有的语言都支持此两种方法. 1)Queue & JoinableQueue queue用来在进程间传递消息,任何可以pickle-able的对象都可以在加入到queue. multiprocessing.JoinableQueue 是 Queue的子类,增加了task_done()和join()方法. task_done()用来告诉queue一个tas

  • Python Queue模块详细介绍及实例

    Python Queue模块 Python中,队列是线程间最常用的交换数据的形式.Queue模块是提供队列操作的模块,虽然简单易用,但是不小心的话,还是会出现一些意外. 创建一个"队列"对象 import Queue q = Queue.Queue(maxsize = 10) Queue.Queue类即是一个队列的同步实现.队列长度可为无限或者有限.可通过Queue的构造函数的可选参数maxsize来设定队列长度.如果maxsize小于1就表示队列长度无限. 将一个值放入队列中 q.p

  • python基于queue和threading实现多线程下载实例

    本文实例讲述了python基于queue和threading实现多线程下载的方法,分享给大家供大家参考.具体方法如下: 主代码如下: #download worker queue_download = Queue.Queue(0) DOWNLOAD_WORKERS = 20 for i in range(DOWNLOAD_WORKERS): DownloadWorker(queue_download).start() #start a download worker for md5 in MD5

  • 简单谈谈python中的Queue与多进程

    最近接触一个项目,要在多个虚拟机中运行任务,参考别人之前项目的代码,采用了多进程来处理,于是上网查了查python中的多进程 一.先说说Queue(队列对象) Queue是python中的标准库,可以直接import 引用,之前学习的时候有听过著名的"先吃先拉"与"后吃先吐",其实就是这里说的队列,队列的构造的时候可以定义它的容量,别吃撑了,吃多了,就会报错,构造的时候不写或者写个小于1的数则表示无限多 import Queue q = Queue.Queue(10

  • Python Queue模块详解

    Python中,队列是线程间最常用的交换数据的形式.Queue模块是提供队列操作的模块,虽然简单易用,但是不小心的话,还是会出现一些意外. 创建一个"队列"对象 import Queue q = Queue.Queue(maxsize = 10) Queue.Queue类即是一个队列的同步实现.队列长度可为无限或者有限.可通过Queue的构造函数的可选参数maxsize来设定队列长度.如果maxsize小于1就表示队列长度无限. 将一个值放入队列中 q.put(10) 调用队列对象的p

  • Python中使用Queue和Condition进行线程同步的方法

    Queue模块保持线程同步 利用Queue对象先进先出的特性,将每个生产者的数据一次存入队列,而每个消费者将依次从队列中取出数据 import threading # 导入threading模块 import Queue # 导入Queue模块 class Producer(threading.Thread):# 定义生产者类 def __init__(self,threadname): threading.Thread.__init__(self,name = threadname) def

  • Java使用Condition控制线程通信的方法实例详解

    本文实例讲述了Java使用Condition控制线程通信的方法.分享给大家供大家参考,具体如下: 一 点睛 当使用Lock对象来保证同步时,Java提供了一个Condition类来保持协调,使用Condition可以让那些已经得到Lock对象.却无法继续执行的线程释放Lock对象,Condtion对象也可以唤醒其他处于等待的线程. Condition 将同步监视锁方法(wait.notify 和 notifyAll)分解成截然不同的对象,以便通过将这些对象与Lock对象组合使用,为每个对象提供多

  • Python中Django框架利用url来控制登录的方法

    本文实例讲述了Python中Django框架利用url来控制登录的方法.分享给大家供大家参考.具体如下: from django.conf.urls.defaults import patterns,url #or use login_required from django.contrib.admin.views.decorators import staff_member_required def login_url(regex, view, *p,**args): """

  • Python中执行存储过程及获取存储过程返回值的方法

    本文实例讲述了Python中执行存储过程及获取存储过程返回值的方法.分享给大家供大家参考,具体如下: 在Pathon中如何执行存储过程呢?可以使用如下方法: 存储过程定义基本如下: ALTER procedure [dbo]. [mysp] @Station varchar ( 50), @SN varchar ( 50), @Info varchar ( 500) output , @Msg varchar ( 500) output 1. 使用adodbapi from adodbapi i

  • Python中字典(dict)合并的四种方法总结

    本文主要给大家介绍了关于Python中字典(dict)合并的四种方法,分享出来供大家参考学习,话不多说了,来一起看看详细的介绍: 字典是Python语言中唯一的映射类型. 映射类型对象里哈希值(键,key)和指向的对象(值,value)是一对多的的关系,通常被认为是可变的哈希表. 字典对象是可变的,它是一个容器类型,能存储任意个数的Python对象,其中也可包括其他容器类型. 字典类型与序列类型的区别: 1. 存取和访问数据的方式不同. 2. 序列类型只用数字类型的键(从序列的开始按数值顺序索引

  • python中实现数组和列表读取一列的方法

    在python中,普通的列表list和numpy中的数组array是不一样的,最大的不同是:一个列表中可以存放不同类型的数据,包括int.float和str,甚至布尔型:而一个数组中存放的数据类型必须全部相同,int或float. 在list中的数据类型保存的是数据的存放的地址,简单的说就是指针,并非数据,这样保存一个list就太麻烦了,例如list1=[1,2,3,4]需要4个指针和四个数据,增加了存储和消耗cpu,而array1=numpy.array([1,2,3,4])只需要存放四个数据

  • Python中的Socket 与 ScoketServer 通信及遇到问题解决方法

    Socket有一个缓冲区,缓冲区是一个流,先进先出,发送和取出的可自定义大小的,如果取出的数据未取完缓冲区,则可能存在数据怠慢.其中[recv(1024)]表示从缓冲区里取最大为1024个字节,但实际取值大小是不确定的,推荐其值小于等于8192. 黏包问题: Socket发送两条连续数据时,可能最终会拼接成一条进行发送 解决方法一: 两条数据间进行延时发送,如[tiem.sleep(0.5) #延时0.5s] 解决方法二: 每次发送后等待对方确认接收信息数据,发送一条后就立即接收等待 解决方法三

  • 在python中利用numpy求解多项式以及多项式拟合的方法

    构建一个二阶多项式:x^2 - 4x + 3 多项式求解 >>> p = np.poly1d([1,-4,3]) #二阶多项式系数 >>> p(0) #自变量为0时多项式的值 3 >>> p.roots #多项式的根 array([3., 1.]) >>> p(p.roots) #多项式根处的值 array([0., 0.]) >>> p.order #多项式的阶数 2 >>> p.coeffs #

  • python中struct模块之字节型数据的处理方法

    简介 这个模块处理python中常见类型数据和Python bytes之间转换.这可用于处理存储在文件或网络连接中的bytes数据以及其他来源.在python中没有专门处理字节的数据类型,建立字节型数据也比较麻烦,我们知道的bytes()函数也只能对无符号整型做处理,并且数据如下(没错,数字为多少就有多少个\x00,我们要是用这种方式来存储大量数据,结果可想而知): va = bytes(1) # va: '\x00' vb = bytes(2) # vb: '\x00\x00' vc = by

  • 在python中实现将一张图片剪切成四份的方法

    如下所示: import cv2 # [1]导入OpenCv开源库 import numpy as np image_path = "F:\\11111111111111111111111111111\\100000.jpg" srcImg = cv2.imread(image_path) # [2]将图片加载到内存 cv2.namedWindow("[srcImg]", cv2.WINDOW_AUTOSIZE) # [3]创建显示窗口 cv2.imshow(&qu

随机推荐