社区所有版块导航
Python
python开源   Django   Python   DjangoApp   pycharm  
DATA
docker   Elasticsearch  
aigc
aigc   chatgpt  
WEB开发
linux   MongoDB   Redis   DATABASE   NGINX   其他Web框架   web工具   zookeeper   tornado   NoSql   Bootstrap   js   peewee   Git   bottle   IE   MQ   Jquery  
机器学习
机器学习算法  
Python88.com
反馈   公告   社区推广  
产品
短视频  
印度
印度  
Py学习  »  Python

二十三、Python队列实现多线程(下篇)

Python开发 • 4 年前 • 307 次点击  
👇👇关注后回复 “进群” ,拉你进程序员交流群👇👇

作者丨 小sen

来源丨Python之王


「@Author:Runsen」

在Python中,主要采用队列和线程的方法来实现多线程。

队列

队列(queue),是先进先出(FIFO, First-In-First-Out)的线性表,在具体应用中通常用链表或者数组来实现,队列只允许在后端(称为rear)进行插入操作,在前端(称为front)进行删除操作,队列的操作方式和堆栈类似,唯一的区别在于队列只允许新数据在后端进行添加。

在Python中队列可以通过内置模块queue导入,具体导入方法:from queue import Queue

queue

queue模块提供了适合多线程编程的先进先出的数据结构,可以用来在生产者和消费者线程之间安全的传递消息或者数据;锁是调用方处理,因此多线程可以安全、方便的使用同一队列实现。

常用属性和方法:

接口描述
put(x)入队
get()出队
empty() 判断队列是否为空
full()判断队列是否未满
qsize()队列的当前长度
task_done()任务结束
join()等待完成

Queue类实现了一个基本的先进先出容器。使用put方法将元素增加到序列的一端,使用get方法从另一端删除,具体代码如下。

import queue

q = queue.Queue()

#添加元素
for i in range(5):
    q.put(i)

#删除元素
while not q.empty():
    print(q.get())

运行上面的程序,你将会看到下面的输出:

0
1
2
3
4

生产者/消费者模式

我们经常会遇到这样的一个问题,这里有成千上万条数据,每次需要取出其中的一条数据进行处理,那么引入多线程该怎么进行任务分配?

我们可以将数据进行分割然后交给多个线程去跑,因为线程间数据的共享的问题。

它包含两类进程:一种只是用来生产数据,例外一种只是用来消费数据.为了串联他们,通常会采用共享的数据区域,就像一个仓库.生产者产生的数据都放入仓库中并不需要关注消费者的行为,消费者只需要从共享仓库中获取数据,并不需要关心生产者的行为.

# -*- coding:utf-8 -*-
# time :2019/4/23 10:13
# Author: Maoli

import threading
import time
import random
MONEY = 0
gLock = threading.Lock()

def Procuder():
    while True:
        global MONEY
        random_money = random.randint(10,100)
        gLock.acquire() #加锁
        MONEY += random_money
        gLock.release() #释放锁
        print ('生产者%s-生产了%d' % (threading.current_thread,random_money))
        time.sleep(0.5)

def Customer():
    while True:
        global MONEY
        random_money = random.randint(10,100)
        if MONEY > random_money:
            print ('消费者%s-消费了:%d' % (threading.current_thread,random_money))
            gLock.acquire()
            MONEY -= random_money
            gLock.release()
        else:
            print ('需要消费的钱为:%d,余额为:%d,' % (random_money,MONEY))
        time.sleep(0.5)

def p_c_test():
    # 执行3个线程,来当作生产者
    for x in range(3):
        th = threading.Thread(target=Procuder)
        th.start()
    # 执行3个线程,来当作消费者
    for x in range(3):
        th = threading.Thread(target=Customer)
        th.start()

if __name__ == "__main__":
    p_c_test()

运行截图如下:

队列实现多线程

在这里我们可以使用队列与线程相结合的方式进行任务分配。在生产消费者模式当中用到的是阻塞型queue。在Python当中,我们最常用的queue就是一个支持多线程场景的阻塞队列

队列线程的思想:首先创建一个全局共享的队列,队列中只存在有限个元素,并将所有的数据逐条加入到队列中,并调用队列的join函数进行等待。之后便可以开启若干线程,线程的任务就是不断的从队列中取数据进行处理就可以了。

# -*- coding:utf-8 -*-
# time :2019/4/23 10:35
# Author: Maoli

import threading
import time
import queue

# 下面来通过多线程来处理Queue里面的任务:
def work(q):
    while True:
        if q.empty():
            return
        else:
            t = q.get()
            print("当前线程sleep {} 秒".format(t))
            time.sleep(t)

def main():
    q = queue.Queue()
    for i in range(5):
        q.put(i)  # 往队列里生成消息
    thread_num = 5
    threads = []
    for i in range(thread_num):
        t = threading.Thread(target=work, args=(q,))
        # args需要输出的是一个元组,如果只有一个参数,后面加,表示元组,否则会报错
        threads.append(t)
    # 创建5个线程
    for i in range(thread_num):
        threads[i].start()
    for i in range(thread_num):
        threads[i].join()

if __name__ == "__main__":
    start = time.time()
    main()
    print('耗时:', time.time() - start)

运行上面的程序,你将会看到下面的输出:

当前线程sleep 0 秒
当前线程sleep 1 秒
当前线程sleep 2 秒
当前线程sleep 3 秒
当前线程sleep 4 秒
耗时:4.002955436706543

今天也学到了很多东西呢,明天有什么新知识呢?真期待鸭~如果喜欢文章可以关注我哦~


Reference

[1]

传送门~: https://github.com/MaoliRUNsen/runsenlearnpy100


-End-

最近有一些小伙伴,让我帮忙找一些 面试题 资料,于是我翻遍了收藏的 5T 资料后,汇总整理出来,可以说是程序员面试必备!所有资料都整理到网盘了,欢迎下载!

点击👆卡片,关注后回复【面试题】即可获取

在看点这里好文分享给更多人↓↓

Python社区是高质量的Python/Django开发社区
本文地址:http://www.python88.com/topic/113928
 
307 次点击