Python 限制线程的最大数量的方法(Semaphore)

Python 中通过 Semaphore 对象可以限制线程的最大数量,从而控制线程的并发访问。Semaphore 是一种同步工具,用于保证多个线程间访问资源的顺序或安全性。

Semaphore在Python的Threading模块中实现。Semaphore维护了一个内部计数器,初始提供一个数量参数,来限制并发线程访问的数量。当我们希望限制一定数量的线程访问共享资源时,可以创建一个 Semaphore 对象,并将计数器初始化为限额值。每当线程获取资源时,Semaphores的计数器就减少一。当计数器值为 0 时,任何尝试获取资源的线程都将被阻塞。

具体来看,Semaphore 的使用方法如下:

创建一个Semaphore对象

import threading

# 创建一个Semaphore对象,并指定信号量的数量
semaphore = threading.Semaphore(3)  # 限制最大并发数量为3

获取锁

获取Semaphore信号量时,可以使用semaphore.acquire()方法,这个方法会判断当前的 Semaphore 对象信号量计数器是否大于0,如果大于0,则立即减少信号量计数器的值并返回True,否则线程会被阻塞。

# 获取 Semaphore,信号量-1
semaphore.acquire()
# ...
# 访问共享资源
# ...
# 释放 Semaphore,信号量+1
semaphore.release()

释放锁

释放Semaphore锁时,需要使用semaphore.release() 方法。Semaphore的计数器会增加1,使得其他线程可以获取信号量访问共享资源。

# 释放 Semaphore,信号量+1
semaphore.release()

示例1

import time
import threading

semaphore = threading.Semaphore(3) # 最大并发数量为3

def worker():
    with semaphore:
        print(f'{threading.current_thread().name} 获取到信号量')
        time.sleep(1) # 模拟执行操作
        print(f'{threading.current_thread().name} 释放信号量')

threads = []
for i in range(5):
    t = threading.Thread(target=worker, name=f'thread-{i}')
    t.start()
    threads.append(t)

for t in threads:
    t.join()

在上面的代码中,我们创建了一个Semaphore对象,设置最大并发数量为3。创建了5个线程,同时在每个线程中获取 Semaphore 对象,打印线程名和时间戳,然后睡眠1s,接着释放 Semaphore 对象,打印线程名和时间戳。

输出结果:

thread-0 获取到信号量
thread-1 获取到信号量
thread-2 获取到信号量
thread-1 释放信号量
thread-3 获取到信号量
thread-2 释放信号量
thread-0 释放信号量
thread-4 获取到信号量
thread-3 释放信号量
thread-4 释放信号量

示例2

另一个使用Semaphore来限制最大并发的例子是运用在爬虫中。爬虫是我们需要获取公共资源的应用之一。比如我们需要获取一个网站中很多商品的数据,如果我们同时向网站发出大量的请求,就容易被网站屏蔽。这个时候使用Semaphore可以很好的避免这个问题,代码可以这样实现:

import requests
import threading

class Crawler:
    SEMAPHORE = threading.Semaphore(3)

    def __init__(self, item):
        self.item = item

    def run(self):
        with self.SEMAPHORE:
            print(f'开始爬取商品{self.item}')
            # 发送请求
            response = requests.get(f'https://www.example.com/products?item={self.item}')
            # 解析数据
            data = self.parse_data(response.text)
            # 保存数据
            self.save_data_to_database(data)
            print(f'商品{self.item}爬取完毕')

    def parse_data(self, data):
         # 爬虫解析数据的具体逻辑
        pass

    def save_data_to_database(self, data):
         # 爬虫保存数据到数据库的具体逻辑
        pass

items = ['item1', 'item2', 'item3', 'item4', 'item5', 'item6']
crawlers = [Crawler(item) for item in items]

threads = [threading.Thread(target=crawler.run, args=()) for crawler in crawlers]
for thread in threads:
    thread.start()

for thread in threads:
    thread.join()

在这个例子中,我们首先创建了一个Semaphore对象并设置最大并发数量为3。然后我们创建了Crawler 类,该类代表了一个爬虫任务,随后在run方法中实现了具体的爬虫逻辑。在 run方法中首先获取Semaphore对象,获取到信号量时打印开始爬取一个商品的信息,随后发送请求,解析数据,保存数据到数据库。完成以上操作之后,释放Semaphore对象,打印结束爬取一个商品的信息。

我们创建了6个Crawler对象,分别代表了需要爬取的6个商品,最后在多线程的环境中运行爬虫。Semaphore对象可以限制最大并发数量,保证在同一时间内只有3个爬虫工作,不会让网站服务被过于频繁的访问。

本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:Python 限制线程的最大数量的方法(Semaphore) - Python技术站

(0)
上一篇 2023年5月18日
下一篇 2023年5月18日

相关文章

  • Python2与python3中 for 循环语句基础与实例分析

    一、Python2与Python3在for循环语句基础上的不同 在Python2中,range()函数返回的是一个列表类型,而在Python3中则返回一个range对象。由于Python2中range()函数返回的是列表类型,在for循环中使用时,会先生成整个列表,再进行迭代,对于大数据量的情况会消耗大量的内存。而在Python3中,range对象只有在被需…

    python 2023年6月6日
    00
  • Python实现yaml与json文件批量互转

    下面是 Python 实现 YAML 与 JSON 文件批量互转的完整攻略: 1. 安装 PyYAML 库 在 Python 中实现 YAML 和 JSON 文件相互转换,需要用到 PyYAML 这个第三方库。我们可以使用 pip 命令进行安装。 在命令行输入以下命令: pip install pyyaml 如果提示权限不足,可以使用管理员权限执行,即在命令…

    python 2023年6月3日
    00
  • 三个python爬虫项目实例代码

    三个python爬虫项目实例代码完整攻略 项目简介 本项目是针对python爬虫初学者提供的三个实例爬虫代码,分别是: 爬取豆瓣图书TOP250的书籍信息 爬取天猫商城的商品信息及评论 爬取GitHub上的开源项目信息 每个项目的代码都包括了完整的数据爬取和存储代码,可以作为初学者进行学习和实践的完整资料。 项目目标 在三个不同的爬虫项目中,我们将能够学习到…

    python 2023年5月14日
    00
  • Pyecharts可视化图片渲染的方法详解

    Pyecharts可视化图片渲染的方法详解 Pyecharts是一个基于Echarts的Python可视化库,可以帮助开发者快速生成各种图表。在使用Pyecharts生成图表后,可以使用不同的方法将图表渲染为图片。以下是Pyecharts可视化图片渲染的方法详解: 使用render方法渲染图片 可以使用render方法将Pyecharts图表渲染为图片。以下…

    python 2023年5月14日
    00
  • 浅谈Python访问MySQL的正确姿势

    浅谈Python访问MySQL的正确姿势 一、MySQL数据库介绍 MySQL是一个关系型数据库管理系统,是最流行的开源数据库之一。由于其易于使用、强大和灵活的属性,它被广泛用于 Web 应用程序的开发。在 Python 中连接 MySQL 数据库需要使用特定的库,如:mysql-connector-python、PyMySQL等。 二、PyMySQL连接M…

    python 2023年5月14日
    00
  • python中(str,list,tuple)基础知识汇总

    Python中(str,list,tuple)基础知识汇总 在Python编程中,字符串(str)、列表(list)和元组(tuple)是三种常用的数据类型。它们都是序列类型,可以存储多个元素,并支持索引、切片等操作。下面将详细介绍Python中(str,list,tuple)基础知识汇总,包括语法、参数、返回值以及示例说明。 字符串(str) 字符串的创建…

    python 2023年5月13日
    00
  • Python实现学生管理系统(面向对象版)

    讲解“Python实现学生管理系统(面向对象版)”的完整攻略: 简介 学生管理系统是面向对象程序设计中的一个典型案例,通过这个实例可以帮助我们更好的理解面向对象程序设计的实现。学生管理系统实际上是一个具有数据管理、数据查询、数据操作的基本程序,可以通过这个程序了解面向对象设计中类的实现方式、属性和方法的绑定、实例的创建等基本概念。 实现步骤 整个学生管理系统…

    python 2023年5月30日
    00
  • Python Tkinter实例——模拟掷骰子

    Python Tkinter是Python标准库中用于GUI(图形用户界面)编程的模块,可以帮助我们构建交互式的图形程序。本篇文章将详细讲解如何使用Python Tkinter模块实现一个简单的掷骰子程序。 安装Python Tkinter模块 Python Tkinter模块是Python标准库内置的一个模块,无需额外安装。使用Tkinter,必须要在代码…

    python 2023年6月3日
    00
合作推广
合作推广
分享本页
返回顶部