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

yizhihongxing

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日

相关文章

  • Python中最大递归深度值的探讨

    单独讨论 Python 中最大递归深度的问题不太有意义。对于这个问题需要从 Python 如何处理递归函数开始,以及递归深度和计算机内存容量有何关系等方面来进行探讨。 Python 如何处理递归函数 Python 中的递归函数和其他语言一样,也是直接或间接调用自身。在一个递归函数中,每一次调用该函数都会在内存中产生一个对应的栈帧。一个栈帧包含这个函数的所有局…

    python 2023年6月3日
    00
  • Python实现上课点名器系统

    Python实现上课点名器系统 系统介绍 本系统使用Python编写,主要用于进行班级上课点名的功能实现。具体功能如下: 随机点名:随机选择一名学生进行点名,并在屏幕上打印该学生的姓名。 全部点名:对班级全部学生进行点名,点名结果将依次在屏幕上打印出每一位学生的姓名。 按照列表点名:根据输入的学生名单进行点名,每次点名都会从列表中随机选择一名学生进行点名,直…

    python 2023年5月18日
    00
  • Python自动录入ERP系统数据

    下面是Python自动录入ERP系统数据的完整攻略,共分为以下几个步骤: 1. 了解ERP系统录入数据的过程 在开始编写Python自动录入ERP系统数据之前,我们需要了解ERP系统录入数据的具体流程,并确定需要录入哪些数据。 2. 安装Python相应的库 在使用Python自动录入ERP系统数据之前,我们需要安装相关的库,如selenium、pandas…

    python 2023年5月19日
    00
  • Python写安全小工具之TCP全连接端口扫描器

    TCP全连接端口扫描器是一种利用TCP协议进行端口扫描的工具,通过模拟TCP连接,对目标主机的所有端口进行扫描,并分析响应数据,从而确定目标主机开放了哪些端口。 本文将详细介绍如何使用Python编写TCP全连接端口扫描器。 确定目标主机 首先,需要确定目标主机的IP地址或域名。可以使用Python中的socket模块中的gethostbyname函数将域名…

    python 2023年6月6日
    00
  • python hashlib加密实现代码

    下面是 Python hashlib 加密实现代码的完整攻略,主要包含以下内容: 模块介绍 加密方法说明 实现代码示例 1. 模块介绍 hashlib 是 Python 的一个加密模块,它提供了多种加密算法,比如 md5、sha1、sha256 等。 2. 加密方法说明 hashlib 模块提供了两种方式进行加密: hashlib.new(name[, da…

    python 2023年6月2日
    00
  • Python 子进程/Popen 标准输出被截断

    【问题标题】:Python subprocess/Popen stdout is truncatedPython 子进程/Popen 标准输出被截断 【发布时间】:2023-04-06 21:15:02 【问题描述】: Popen stdout 的输出与从 Shell 运行命令或使用 os.system 不同: cmd = [‘git’, ‘diff’, c…

    Python开发 2023年4月7日
    00
  • python编写小程序探测linux端口占用情况

    下面是详细讲解 “Python编写小程序探测Linux端口占用情况”的完整攻略。 1. 需求分析 首先我们需要明确这个小程序的需求。本程序需要接受用户输入一个IP地址和端口号,然后通过扫描这个IP地址和端口号,判断此端口是否被占用。最后将扫描结果输出给用户。 2. 程序设计 接下来我们进行程序设计。首先,我们需要导入 socket 模块来实现IP地址和端口的…

    python 2023年5月23日
    00
  • python使用jpype导入多个Jar的异常问题及解决

    介绍 在使用 Python 调用 Java 的过程中,如果需要导入多个 Jar 包,可能会遇到一些异常问题。本篇文章将详细讲解如何解决这个问题。 问题探究 先来看看一个简单的例子。假设我们有两个 Jar 包:a.jar 和 b.jar。以下代码尝试调用 b.jar 中的一个类: import jpype jar_path = ‘b.jar’ jpype.st…

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