zoukankan      html  css  js  c++  java
  • Python中Queue模块及多线程使用

            Python的Queue模块提供一种适用于多线程编程的FIFO实现。它可用于在生产者(producer)和消费者(consumer)之间线程安全(thread-safe)地传递消息或其它数据,因此多个线程可以共用同一个Queue实例。Queue的大小(元素的个数)可用来限制内存的使用。

    Basic FIFO Queue

    Queue类实现了一个基本的先进先出(FIFO)容器,使用put()将元素添加到序列尾端,get()从队列尾部移除元素。

    LIFO Queue

    与标准FIFO实现Queue不同的是,LifoQueue使用后进先出序(会关联一个栈数据结构)。

    Priority Queue(优先队列)

    除了按元素入列顺序外,有时需要根据队列中元素的特性来决定元素的处理顺序。例如,财务部门的打印任务可能比码农的代码打印任务优先级更高。PriorityQueue依据队列中内容的排序顺序(sort order)来决定那个元素将被检索。

    Using Queues with Threads

    queue介绍

    • queue是python中的标准库,俗称队列,可以直接import 引用,在python2.x中,模块名为Queue
    • 在python中,多个线程之间的数据是共享的,多个线程进行数据交换的时候,不能够保证数据的安全性和一致性,所以当多个线程需要进行数据交换的时候,队列就出现了,队列可以完美解决线程间的数据交换,保证线程间数据的安全性和一致性

    queue模块有三种队列及构造函数:

    1. Python queue模块的FIFO队列先进先出。 class queue.Queue(maxsize)
    2. LIFO类似于堆,即先进后出。 class queue.LifoQueue(maxsize)
    3. 还有一种是优先级队列级别越低越先出来。 class queue.PriorityQueue(maxsize)

    queue模块中的常用方法:

    • queue.qsize() 返回队列的大小
    • queue.empty() 如果队列为空,返回True,反之False
    • queue.full() 如果队列满了,返回True,反之False
    • queue.full 与 maxsize 大小对应
    • queue.get([block[, timeout]])获取队列,timeout等待时间
    • queue.get_nowait() 相当queue.get(False)
    • queue.put(item) 写入队列,timeout等待时间
    • queue.put_nowait(item) 相当queue.put(item, False)
    • queue.task_done() 在完成一项工作之后,queue.task_done()函数向任务已经完成的队列发送一个信号
    • queue.join() 实际上意味着等到队列为空,再执行别的操作

    代码例子:

    # coding: utf-8
    
    from queue import Queue
    
    # Queue是python标准库中的线程安全的队列(FIFO)实现,提供了一个适用于多线程编程的先进先出的数据结构,即队列,用来在生产者和消费者线程之间的信息传递
    def test_queue():
    
        q=Queue(10)
        for i in range(5):
            q.put(i)
        while not q.empty():
            print(q.get())
    
    def test_LifoQueue():
        import queue
        # queue.LifoQueue() #后进先出->堆栈
        q = queue.LifoQueue(3)
        q.put(1)
        q.put(2)
        q.put(3)
        print(q.get())
        print(q.get())
        print(q.get())
    
    def test_PriorityQueue():
        import queue
        # queue.PriorityQueue() #优先级
        q = queue.PriorityQueue(3)  # 优先级,优先级用数字表示,数字越小优先级越高
        q.put((10, 'a'))
        q.put((-1, 'b'))
        q.put((100, 'c'))
        print(q.get())
        print(q.get())
        print(q.get())
    
    
    # Python queue队列,实现并发,在网站多线程推荐最后也一个例子,比这货简单,但是不够规范
    
    from queue import Queue  # Queue在3.x中改成了queue
    import random
    import threading
    import time
    from threading import Thread
    
    class Producer(threading.Thread):
        """
        Producer thread 制作线程
        """
        def __init__(self, t_name, queue):  # 传入线程名、实例化队列
            threading.Thread.__init__(self, name=t_name)  # t_name即是threadName
            self.data = queue
    
        """
        run方法 和start方法:
        它们都是从Thread继承而来的,run()方法将在线程开启后执行,
        可以把相关的逻辑写到run方法中(通常把run方法称为活动[Activity]);
        start()方法用于启动线程。
        """
    
        def run(self):
            for i in range(5):  # 生成0-4五条队列
                print("%s: %s is producing %d to the queue!" % (time.ctime(), self.getName(), i))  # 当前时间t生成编号d并加入队列
                self.data.put(i)  # 写入队列编号
                time.sleep(random.randrange(10) / 5)  # 随机休息一会
            print("%s: %s producing finished!" % (time.ctime(), self.getName))  # 编号d队列完成制作
    
    
    class Consumer(threading.Thread):
        """
        Consumer thread 消费线程,感觉来源于COOKBOOK
        """
        def __init__(self, t_name, queue):
            threading.Thread.__init__(self, name=t_name)
            self.data = queue
    
        def run(self):
            for i in range(5):
                val = self.data.get()
                print("%s: %s is consuming. %d in the queue is consumed!" % (time.ctime(), self.getName(), val))  # 编号d队列已经被消费
                time.sleep(random.randrange(10))
            print("%s: %s consuming finished!" % (time.ctime(), self.getName()))  # 编号d队列完成消费
    
    
    def main():
        """
        Main thread 主线程
        """
        queue = Queue()  # 队列实例化
        producer = Producer('Pro.', queue)  # 调用对象,并传如参数线程名、实例化队列
        consumer = Consumer('Con.', queue)  # 同上,在制造的同时进行消费
        producer.start()  # 开始制造
        consumer.start()  # 开始消费
        """
        join()的作用是,在子线程完成运行之前,这个子线程的父线程将一直被阻塞。
       join()方法的位置是在for循环外的,也就是说必须等待for循环里的两个进程都结束后,才去执行主进程。
        """
        producer.join()
        consumer.join()
        print('All threads terminate!')
    
    
    
    if __name__=="__main__":
    
        test_queue()
    
        print("=====后进先出=====")
        test_LifoQueue()
    
        print("=====优先级======")
        test_PriorityQueue()
    
        main()

    线程模块

    - 多线程主要的内容:直接进行多线程操作,线程同步,带队列的多线程;

    Python3 通过两个标准库 _thread 和 threading 提供对线程的支持。

    _thread 提供了低级别的、原始的线程以及一个简单的锁,它相比于 threading 模块的功能还是比较有限的。

    threading 模块除了包含 _thread 模块中的所有方法外,还提供的其他方法:

    • threading.currentThread(): 返回当前的线程变量。
    • threading.enumerate(): 返回一个包含正在运行的线程的list。正在运行指线程启动后、结束前,不包括启动前和终止后的线程。
    • threading.activeCount(): 返回正在运行的线程数量,与len(threading.enumerate())有相同的结果。

    除了使用方法外,线程模块同样提供了Thread类来处理线程,Thread类提供了以下方法:

    • run(): 用以表示线程活动的方法。
    • start():启动线程活动。
    • join([time]): 等待至线程中止。这阻塞调用线程直至线程的join() 方法被调用中止-正常退出或者抛出未处理的异常-或者是可选的超时发生。
    • isAlive(): 返回线程是否活动的。
    • getName(): 返回线程名。
    • setName(): 设置线程名。
    #queue 多线程各个线程的运算的值放到一个队列中,到主线程的时候再拿出来,以此来代替
    #return的功能,因为在线程是不能返回一个值的
    # https://www.cnblogs.com/zephyr-1/p/6043785.html
    import time import threading from Queue import Queue def job(l,q): q.put([i**2 for i in l]) def multithreading(data): q = Queue() threads = [] for i in xrange(4): t = threading.Thread(target = job,args = (data[i],q)) t.start() threads.append(t) for thread in threads: thread.join() results = [] for _ in range(4): results.append(q.get()) print results if __name__ == "__main__": data = [[1,2,3],[4,5,6],[3,4,3],[5,5,5]] multithreading(data) [[1, 4, 9], [16, 25, 36], [9, 16, 9], [25, 25, 25]]
  • 相关阅读:
    一片非常有趣的文章 三分钟读懂TT猫分布式、微服务和集群之路
    mysql+mycat搭建稳定高可用集群,负载均衡,主备复制,读写分离
    mycat读写分离+垂直切分+水平切分+er分片+全局表 测试
    LVS Nginx HAProxy 优缺点
    nginx map配置根据请求头不同分配流量到不同后端服务
    Javamail发送邮件
    java发送html模板的高逼格邮件
    学习openresty时,nginx的一个坑
    mysql数据导出golang实现
    mysql支持原生json使用说明
  • 原文地址:https://www.cnblogs.com/ranjiewen/p/10218751.html
Copyright © 2011-2022 走看看