零基础学 Python(2018 版)
尹会生
前游戏公司技术总监,前新浪网技术经理
80141 人已学习
新⼈⾸单¥68
课程目录
已完结/共 72 讲
第一章 :Python介绍和安装 (3讲)
第二章 :Python基础语法 (3讲)
第四章 :条件与循环 (5讲)
第五章 :映射与字典 (2讲)
第六章 :文件和输入输出 (2讲)
第七章 :错误和异常 (1讲)
第九章 :模块 (1讲)
第十章 :语法规范 (1讲)
第十一章 :面向对象编程 (4讲)
第十二章 :多线程编程 (2讲)
第十六章 :综合案例 & 结课测试 (1讲)
特别放送 (1讲)
零基础学 Python(2018 版)
登录|注册
留言
16
收藏
沉浸
阅读
分享
手机端
回顶部
当前播放: 40 | 经典的生产者和消费者问题
00:00 / 00:00
高清
  • 高清
1.0x
  • 2.0x
  • 1.5x
  • 1.25x
  • 1.0x
  • 0.75x
  • 0.5x
网页全屏
全屏
00:00
付费课程,可试看
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与search的区别
46 | 正则表达式库替换函数sub()的实例
47 | 日期与时间函数库
48 | 数学相关库
49 | 使用命令行对文件和文件夹操作
50 | 文件与目录操作库
51 | 机器学习的一般流程与NumPy安装
52 | NumPy的数组与数据类型
53 | NumPy数组和标量的计算
54 | NumPy数组的索引和切片
55 | pandas安装与Series结构
56 | Series的基本操作
57 | Dataframe的基本操作
58 | 层次化索引
59 | Matplotlib的安装与绘图
60 | 机器学习分类的原理
61 | Tensorflow的安装
62 | 根据特征值分类的模型和代码
63 | 网页数据的采集与urllib库
64 | 网页常见的两种请求方式get和post
65 | HTTP头部信息的模拟
66 | requests库的基本使用
67 | 结合正则表达式爬取图片链接
68 | Beautiful Soup的安装和使用
69 | 使用爬虫爬取新闻网站
70 | 使用爬虫爬取图片链接并下载图片
强势回归:零基础学Python2022版来啦!
71 | 如何分析源代码并设计合理的代码结构&结课测试
本节摘要

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

https://gitee.com/geektime-geekbang/geekbangpython

登录 后留言

全部留言(16)

  • 最新
  • 精选
asia~wz[]niubility[]
消费者的task_done()还是不清楚用来干什么

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

2018-10-30
10
一直都在
老师,我的代码不知道出什么问题了,生产者一直在生产数据,消费者没有进行消费 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()时会“暂停”,直到有数据写入队列,所以你只看到打印生产数据,没看到消费数据

2019-01-28
4
海生
这个还得对队列读写时队列的空满做判断吧?

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

2018-08-05
4
littlePerfect
老师, queue 为什么要设置成全局变量?

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

2019-01-17
2
3
爱学习
ImportError: cannot import name 'Queue' from 'queue' 老师,我在导入时报错,是版本问题吗? 语句跟您的一样: from queue import Queue

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

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

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

2019-02-09
1
start
全局变量queue是临界资源,这样写多线程会有并发问题吧

作者回复: 这里的queue用的python库,它是线程安全的,里面实现了锁机制

2020-03-27
Geek_b6e557
线程的作用说了,线程的运行原理是什么?

作者回复: python多线程和linux的线程原理相同,参考操作系统的线程原理即可

2020-03-26
泡芙
老师,为什么要使用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-08-25
MD
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-03-07
收起评论