下载APP
登录
关闭
讲堂
算法训练营
Python 进阶训练营
企业服务
极客商城
客户端下载
兑换中心
渠道合作
推荐作者
当前播放: 40 | 经典的生产者和消费者问题
00:00 / 00:00
标清
  • 标清
1.0x
  • 2.0x
  • 1.5x
  • 1.25x
  • 1.0x
  • 0.5x
网页全屏
全屏
00:00
付费课程,可试看

零基础学Python

共71讲 · 71课时·约540分钟
16024
免费
01 | Python语言的特点
免费
02 | Python的发展历史与版本
免费
03 | Python的安装
免费
04 | Python程序的书写规则
免费
05 | 基础数据类型
免费
06 | 变量的定义和常用操作
07 | 序列的概念
08 | 字符串的定义和使用
09 | 字符串的常用操作
10 | 元组的定义和常用操作
11 | 列表的定义和常用操作
12 | 条件语句
13 | for循环
14 | while循环
15 | for循环语句中的if嵌套
16 | while循环语句中的if嵌套
17 | 字典的定义和常用操作
18 | 列表推导式与字典推导式
19 | 文件的内建函数
20 | 文件的常用操作
21 | 异常的检测和处理
22 | 函数的定义和常用操作
23 | 函数的可变长参数
24 | 函数的变量作用域
25 | 函数的迭代器与生成器
26 | Lambda表达式
27 | Python内建函数
28 | 闭包的定义
29 | 闭包的使用
30 | 装饰器的定义
31 | 装饰器的使用
32 | 自定义上下文管理器
33 | 模块的定义
34 | PEP8编码规范
35 | 类与实例
36 | 如何增加类的属性和方法
37 | 类的继承
38 | 类的使用-自定义with语句
39 | 多线程编程的定义
40 | 经典的生产者和消费者问题
41 | Python标准库的定义
42 | 正则表达式库re
43 | 正则表达式的元字符
44 | 正则表达式分组功能实例
45 | 正则表达式库函数match与s...
46 | 正则表达式库替换函数sub...
47 | 日期与时间函数库
48 | 数学相关库
49 | 使用命令行对文件和文件夹...
50 | 文件与目录操作库
51 | 机器学习的一般流程与NumP...
52 | NumPy的数组与数据类型
53 | NumPy数组和标量的计算
54 | NumPy数组的索引和切片
55 | pandas安装与Series结构
56 | Series的基本操作
57 | Dataframe的基本操作
58 | 层次化索引
59 | Matplotlib的安装与绘图
60 | 机器学习分类的原理
61 | Tensorflow的安装
62 | 根据特征值分类的模型和代...
63 | 网页数据的采集与urllib库
64 | 网页常见的两种请求方式ge...
65 | HTTP头部信息的模拟
66 | requests库的基本使用
67 | 结合正则表达式爬取图片链...
68 | Beautiful Soup的安装和...
69 | 使用爬虫爬取新闻网站
70 | 使用爬虫爬取图片链接并下...
71 | 如何分析源代码并设计合理...
本节摘要

课程源码、课件及课后作业地址:

https://github.com/wilsonyin123/geekbangpython

精选留言(11)

  • 消费者的task_done()还是不清楚用来干什么

    作者回复: task_done()是配合join()使用的,join() 会让队列一直处于阻塞状态,直到queue里面所有的message都被get()取出来调用了task_done()才能返回,不用这个函数会让join()出现无限挂起的问题,不符合我们写程序的预期。
            它和join()一起使用来判断队列里是否还有message需要处理的一种机制,如果看它的代码实现,会发现它通过信号与join()进行配合的。
            或许在初学阶段,大家更容易理解这种用法
    while not workQueue.empty():
        pass
    就是一直循环,直到队列为空。
            两种机制都可以判断为队列是否为空,看你需要那种方法和想要在哪种场景下使用。

    4
  • 2019-01-17
    老师, queue 为什么要设置成全局变量?

    作者回复: 在文件内,模块(函数)外声明的都是全局变量,
    这里使用的global是声明在类中使用的queue是全局变量,避免class内部误声明同名的queue变量发生冲突。

    1
    3
  • 2019-01-28
    老师,我的代码不知道出什么问题了,生产者一直在生产数据,消费者没有进行消费
    from threading import Thread, current_thread
    import random
    import time
    from queue import Queue

    queue = Queue(5)


    class ProducerThread(Thread):
        def run(self):
            name = current_thread().getName()
            nums = range(100)
            global queue
            while True:
                num = random.choice(nums)
                print('生产者 %s 生产了数据 %s' % (name, num))
                t = random.randint(1, 3)
                time.sleep(t)
                print('生产者 %s 休眠了 %s 秒' % (name, t))


    class ConsumerThread(Thread):
        def run(self):
            name = current_thread().getName()
            global queue
            while True:
                num = queue.get()
                queue.task_done()
                print('消费者 %s 消耗了数据 %s' % (name, num))
                t = random.randint(1, 5)
                time.sleep(t)
                print('消费者 %s 休眠了 %s 秒' % (name, t))


    p1 = ProducerThread(name='p1')
    p1.start()
    c1 = ConsumerThread(name='c1')
    c1.start()
    展开

    作者回复: 问题出在产生了一个数据,但是并没有将他放在队列里面(queue.put(num))啊,当第二个线程执行到num = queue.get()时会“暂停”,直到有数据写入队列,所以你只看到打印生产数据,没看到消费数据

    2
  • 2018-08-05
    这个还得对队列读写时队列的空满做判断吧?

    作者回复: 一定要判断的,我这里没有演示是因为queue包对已满队列有自己的处理机制,而不是抛出异常。可以自己尝试一下,如果只往队列写,不读取会发生什么结果?通过官方文档查看如何判断队列是否已满?

    2
  • 2019-02-09
    看到你给其他同学的留言,好像是说队列空位时,执行到num = queue.get()时会“暂停”。 为什么会暂停呢? 我们没有给它暂停的指令啊。是这个方法自带的功能吗?

    作者回复: 是的,这是引用了queue库时引入的,类似异常处理。

    1
  • 2019-08-25
    老师,为什么要使用task.done()方法来同步和等待呢?不进行同步和等待,这个例子里看着没有什么影响呀?

    作者回复: task_done()作用:如果 join() 当前正在阻塞,在所有条目都被处理后,将解除阻塞

    参考等待排队的任务被完成的示例:

    import queue
    import threading

    def worker():
        while True:
            item = q.get()
            if item is None:
                break
            print(item, 'run')
            #注释q.task_done()这行查看程序运行结果进行对比
            q.task_done()


    q = queue.Queue()
    threads = []
    num_worker_threads = 2

    for i in range(num_worker_threads):
        t = threading.Thread(target=worker)
        t.start()
        threads.append(t)

    for item in range(10):
        q.put(item)

    # block until all tasks are done
    q.join()

    # stop workers
    for i in range(num_worker_threads):
        q.put(None)
    for t in threads:
        t.join()

  • 2019-04-24
    老师,您好,关于queue变量为什么设置为global的问题,我看到您已经给出了解释。
    但是还是很难理解,可否举个具体一点的例子说明呢?
  • 2019-03-19
    ImportError: cannot import name 'Queue' from 'queue'
    老师,我在导入时报错,是版本问题吗?
    语句跟您的一样: from queue import Queue

    作者回复: 是否您的文件名就是 queue.py 呢?

  • 2019-03-07
    p1 = ProducerThread(name='p1')这个有点不明白,前面的代码里面name= current_thread().getName() 表示name变量为当前线程名,实例中第一个参数就是线程名?为什么不适用__init__初始化name?

    作者回复: p1是ProducerThread()类的实例化,ProducerThread()继承了threading类,当我调用p1.start()方法时,class ProducerThread(Thread)类会自动调用run()方法。

    首先强调一下这段代码的目的性:这里我写ProducerThread(name='p1')目的是想使用 p1 c1 c2的名字替代 thread-1 、 thread-2、 thread-3 ...这样的默认名称,为的是输出时方便大家看效果。这个功能要在实例化的时候使用,所以不能用__init__ 初始化name

    python传参是可以传“关键字参数”的,这里使用的name='p1'并不是第一个参数是线程名,而是我在run()方法定义了name变量,实例化的时候重传name进行覆盖。

  • 2019-02-09
    老师,当队列为空的消费者去消费的时候发生了什么?
    为什么没有打印出来说消费为0?根据代码,消费者会一直去队列去查询是有有可用消费,但好像什么都没发生似的?自己没尝试出来。
  • 2019-01-17
    老师, global 为什么会设置成全局变量?
    1