多线程通信方式

共享变量

创建全局变量,多个线程公用一个全局变量,方便简单。但是坏处就是共享变量容易出现数据竞争,不是线程安全的,解决方法就是使用互斥锁。

# 示例代码,模拟爬虫

import threading

import time

url_lists = []

def get_urls():

# 模拟爬取url

global url_lists

print("get urls started")

for i in range(20):

url_lists.append(f"https://www.baidu.com/{i}")

print("get urls end")

def get_detail():

# 模拟爬取页面内容

global url_lists

if len(url_lists):

url = url_lists.pop()

print("get detail started")

time.sleep(2)

print("get detail end")

if __name__ == '__main__':

# 爬取url链接

thread_get_urls = threading.Thread(target=get_urls)

thread_get_urls.start()

# 开启10个线程爬取

for i in range(10):

t = threading.Thread(target=get_detail)

t.start()

将共享变量以参数传递进去

import threading

import time

url_lists = []

def get_urls(url_lists):

# 模拟爬取url

while True:

print("get urls started")

for i in range(20):

url_lists.append(f"https://www.baidu.com/{i}")

print("get urls end")

def get_detail(url_lists):

# 模拟爬取页面内容

while True:

if len(url_lists):

url = url_lists.pop()

print("get detail started")

time.sleep(2)

print("get detail end")

if __name__ == '__main__':

# 爬取url链接

thread_get_urls = threading.Thread(target=get_urls, args=(url_lists, ))

thread_get_urls.start()

# 开启10个线程爬取

for i in range(10):

t = threading.Thread(target=get_detail, args=(url_lists, ))

t.start()

将共享变量单独放在其他py文件中,应用场景变量很多时能方便管理,比如放在variables.py中

import threading

import time

import variables

def get_urls():

# 模拟爬取url

url_lists = variables.url_lists

while True:

print("get urls started")

for i in range(20):

url_lists.append(f"https://www.baidu.com/{i}")

print("get urls end")

def get_detail():

# 模拟爬取页面内容

url_lists = variables.url_lists

while True:

if len(url_lists):

url = url_lists.pop()

print("get detail started")

time.sleep(2)

print("get detail end")

if __name__ == '__main__':

# 爬取url链接

thread_get_urls = threading.Thread(target=get_urls)

thread_get_urls.start()

# 开启10个线程爬取

for i in range(10):

t = threading.Thread(target=get_detail)

t.start()

队列

线程间使用队列进行通信,因为队列所有方法都是线程安全的,所以不会出现线程竞争资源的情况。Queue常用的方法。

put(item, block=True, timeout=None)

阻塞方式将item添加进队列中,如果队列满了则一直等待,如果给定了timeout则等待timeout;如果block为Flase,则为非阻塞式,队列满时再添加则直接抛出错误

put_nowait(item)

非阻塞式添加

get(block=True, timeout=None)

阻塞式获取,队列为空时,则一直等待,或者等待给定timeout秒

get_nowait()

非阻塞式获取值

qsize()

返回队列大小

empty()

返回布尔值,判断队列是否为空

full()

返回布尔值,判断队列是否满了

join()

一直阻塞直到队列中的所有项目都已获取并处理完毕。

每当任务(示例:未爬取过的url)添加到队列时,未完成任务的计数就会增加。 每当消费者线程(示例:爬取网页内容的函数)调用task_done()以指示检索到该项目并且其上的所有工作都已完成时,计数就会下降。 当未完成任务的数量降至零时,join()取消阻塞

task_done()

表明以前排队的任务(示例:使用一个url爬取网页内容完成)已完成。

由队列使用者线程使用。每次调用get()方法从队列中获取任务,如果任务处理完毕,则条用task_done()方法,告知等待的队列(queue.join()这里在等待)任务的处理已完成。

如果join()当前正在阻塞,则它将在所有项目都已处理后恢复(这意味着已为每个已放入队列的项目收到task_done()调用)。

如果调用的次数超过队列中放置的项目,则引发ValueError。

最后两个方法,是我开始最不能理解的,后面看了很多博客,大概知道她们的作用。下面我以生产者消费者示例代码演示。代码从另外个哥们那里获取的,但是做了些修改

from threading import Thread

import time

import random

from queue import Queue

from collections import deque

# 创建队列,设置队列最大数限制为3个

queue = Queue(3)

# 生产者线程

class Pro_Thread(Thread):

def run(self):

# 原材料准备,等待被生产

tasks = deque([1, 2, 3, 4, 5, 6, 7, 8])

global queue

while True:

try:

# 从原材料左边开始生产,如果tasks中没有元素,调用popleft()则会抛出错误

task = tasks.popleft()

queue.put(task)

print("生产", task, "现在队列数:", queue.qsize())

# 休眠随机时间

time.sleep(random.random())

# 如果原材料被生产完,生产线程跳出循环

except IndexError:

print("原材料已被生产完毕")

break

print("生产完毕")

# 消费者线程

class Con_Thread(Thread):

def run(self):

global queue

while True:

if not queue.empty():

# 通过get(),这里已经将队列减去了1

task = queue.get()

time.sleep(2)

# 发出完成的信号,不发的话,join会永远阻塞,程序不会停止

queue.task_done()

print("消费", task)

else:

break

print("消费完毕")

# r入口方法,主线程

def main():

Pro_1 = Pro_Thread()

# 启动线程

Pro_1.start()

# 这里休眠一秒钟,等到队列有值,否则队列创建时是空的,主线程直接就结束了,实验失败,造成误导

time.sleep(1)

for i in range(2):

Con_i = Con_Thread()

# 启动线程

Con_i.start()

global queue

# 接收信号,主线程在这里等待队列被处理完毕后再做下一步

queue.join()

# 给个标示,表示主线程已经结束

print("主线程结束")

if __name__ == '__main__':

main()

threading.Thread().join()方法和queue.join)()的区别

线程的join()是主线程等待子线程的执行完毕再执行

队列的join()是主线程等待队列中的任务都消耗完再执行

python queue join,python3多线程通信方式,主要理解队列的join()和task_done()方法相关推荐

  1. Python线程,以及多线程带来的数据错乱和死锁的解决方法

    摘至本人有道云笔记<Python线程> 1.python多线程的创建 在Python中,同样可以实现多线程,有两个标准模块thread和threading,不过我们主要使用更高级的thre ...

  2. 二级python考试安装python3.5.3时遇到的一些问题及解决方法

    问题一:安装python第一个遇到的问题就是有旧版或者新版的python 解决方法: 第一步,把不常用的那个版本的python所在安装目录下的pythonw.exe和python.exe改为pytho ...

  3. python queue 模块教程

    queue 模块即队列,特别适合处理信息在多个线程间安全交换的多线程程序中.下面我们对 queue 模块进行一个详细的使用介绍. 1 queue 模块定义的类和异常 queue 模块定义了以下四种不同 ...

  4. Python queue

    Python queue queue 即队列,特别适合多线程间安全交换信息. 一.四种不同类型的队列 1.queue.Queue(maxsize=0) 先进先出 (First In First Out ...

  5. python多线程爬虫实例-Python3多线程爬虫实例讲解代码

    多线程概述 多线程使得程序内部可以分出多个线程来做多件事情,充分利用CPU空闲时间,提升处理效率.python提供了两个模块来实现多线程thread 和threading ,thread 有一些缺点, ...

  6. python queue threading_Python 多线程 -thread threading Queue- 简单学习

    Python 多线程 -thread threading Queue- 简单学习 在实际工作过程中,会出现需要并发的做一些事情,例如一台机器测到几千台机器的网络连通性,如果你单线程一台一台测的话,会花 ...

  7. python进阶 多线程编程 —— threading和queue库实现多线程编程

    python进阶 多线程编程 -- threading和queue库实现多线程编程) 摘要 多线程实现逻辑封装 模型参数选择实例 摘要 本文主要介绍了利用python的 threading和queue ...

  8. python3多线程queue_Python多线程(3)——Queue模块

    Queue模块支持先进先出(FIFO)队列,支持多线程的访问,包括一个主要的类型(Queue)和两个异常类(exception classes). Python 2 中的Queue模块在Python ...

  9. python queue查询空_【Python】多线程爬虫案例

    爬取博客园文章列表 爬取博客园文章列表,假设页面的URL是https://www.cnblogs.com/loaderman 要求:使用requests获取页面信息,用XPath / re 做数据提取 ...

  10. 【python教程】对多线程中join()的详细教程

    在 Python 的多线程编程中,经常碰到 thread.join()这样的代码.那么今天咱们用实际代码来解释一下 join 函数的作用. 一. 当一个进程启动之后,会默认产生一个主线程,因为线程是程 ...

最新文章

  1. Libevent调用
  2. Android--Otto事件总线 -- 组件之间通讯框架使用 --模式解析
  3. 精通JavaScript攻击框架:AttackAPI
  4. 重载与重写(overload and override)
  5. ssh oracle id native,hibernate解决oracle的id自增?
  6. Facebook 的大牛组长什么样?
  7. 知道一点怎么设直线方程_直线初步
  8. java 取栈顶元素_java集合系列(7)Stack
  9. 鼠标放到图片上替换图片,改变样式。
  10. 40个经典单片机实验_太经典啦!单片机常用的14个C语言算法(附详细代码)
  11. 快速排序算法_大佬的快速排序算法,果然不一样
  12. win7如何添加终端服务器,Win7系统如何添加超级终端?Windows7系统超级终端的添加方法...
  13. 【马克思主义基本原理】--第一章--【世界的物质性及发展规律】
  14. 【JS】中文繁简转换
  15. “神奇小子”于品海 再展零成本收购绝技
  16. 【TUG 话题探讨 005】TiDB 生态工具(DM、TiCDC等)使用场景及常见问题
  17. python面向对象高级
  18. 白鹭安装node_Mac OS X 系统下安装和部署Egret引擎开发环境
  19. 为miniconda设置环境变量
  20. 【分层强化学习】HAC源码解读

热门文章

  1. 【狂神说Redis】2Redis入门 2-1概述
  2. linux编译安装慢,解决 Linux 下 Jenkins 安装插件很慢的问题
  3. c语言二级考试题型2016,2016年计算机二级《C语言》操作试题及答案
  4. mysql shrink_MySQL Group Replication内存使用分析和优化-1
  5. jQuery简单好用的JavaScript代码库略解使用
  6. 常平计算机培训班,常平大朗CNC编程培训速成班,一个月学会UG编程
  7. python 字典排序成绩_原来python中dict()的高级用法可以这样实现!真是让我长了见识...
  8. xss绕过尖括号和双括号_【Web安全入门】三个技巧教你玩转XSS漏洞
  9. lotus Domino调用webservice
  10. C#语言和SQL Server数据库技术_前四章错题