首页 > 编程语言 >python--多线程:锁 、全局锁、Queue队列以及线程池

python--多线程:锁 、全局锁、Queue队列以及线程池

时间:2023-04-23 11:46:12浏览次数:37  
标签:thread get python Queue 队列 线程 import 多线程

关于如何加锁,获取钥匙,释放锁:

  • lock = threading.Lock():生成锁对象,全局唯一;
  • lock.acquire():获取锁。未获取到会阻塞程序,直到获取到锁才会往下执行;
  • lock.release():释放锁,归回后,其他人也可以调用;

  【注意事项】:lock.acquire() 和 lock.release()必须成对出现,否则就有可能造成死锁。

  为了规避这个问题,可以使用使用上下文管理器来加锁。如下所示:

  

import threading
lock = threading.Lock()
with lock:
    # 这里写想要实现的代码
    pass

关于GIL(全局锁):

  任何Python线程执行前,必须先获得GIL锁,然后,每执行100条字节码,解释器就自动释放GIL锁,让别的线程有机会执行。这个GIL全局锁实际上把所有线程的执行代码都给上了锁,所以,多线程在Python中只能交替执行,即使100个线程跑在100核CPU上,也只能用到1个核。

  【重点】python解释器中任意时刻都只有一个线程在执行;

关于Queue队列

  谈及多线程,就不得不说Queue队列,这是从一个线程向另一个线程发送数据最安全的方式。创建一个被多个线程共享的 Queue 对象,这些线程通过使用put() 和 get() 操作来向队列中添加或者删除元素。

from queue import Queue
# maxsize默认为0,不受限
# 一旦>0,而消息数又达到限制,q.put()也将阻塞
q = Queue(maxsize=0)

# 阻塞程序,等待队列消息。
q.get()

# 获取消息,设置超时时间
q.get(timeout=5.0)

# 发送消息
q.put()

# 等待所有的消息都被消费完
q.join()

# 以下三个方法,知道就好,代码中不要使用

# 查询当前队列的消息个数
q.qsize()

# 队列消息是否都被消费完,True/False
q.empty()

# 检测队列里消息是否已满
q.full()

关于线程池:

在Python3中,创建线程池是通过concurrent.futures函数库中的ThreadPoolExecutor类来实现的。

import Queue
import threading
import time

'''
这个简单的例子的想法是通过:
1、利用Queue特性,在Queue里创建多个线程对象
2、那我执行代码的时候,去queue里去拿线程!
如果线程池里有可用的,直接拿。
如果线程池里没有可用,那就等。
3、线程执行完毕,归还给线程池
'''

class ThreadPool(object): #创建线程池类
    def __init__(self,max_thread=20):#构造方法,设置最大的线程数为20
        self.queue = Queue.Queue(max_thread) #创建一个队列
        for i in xrange(max_thread):#循环把线程对象加入到队列中
            self.queue.put(threading.Thread)
            #把线程的类名放进去,执行完这个Queue

    def get_thread(self):#定义方法从队列里获取线程
        return self.queue.get()

    def add_thread(self):#定义方法在队列里添加线程
        self.queue.put(threading.Thread)

pool = ThreadPool(10)

def func(arg,p):
    print arg
    time.sleep(2)
    p.add_thread() #当前线程执行完了,我在队列里加一个线程!

for i in xrange(300):
    thread = pool.get_thread() #线程池10个线程,每一次循环拿走一个!默认queue.get(),如果队列里没有数据就会等待。
    t = thread(target=func,args=(i,pool))
    t.start()

关于回调函数add_done_callback

回调函数是在调用线程完成后再调用的,在同一个线程中。

import requests
import os
import random
import concurrent.futures as futures

def download_img(url):
    resp = requests.get(url)
    filename = os.path.split(url)[1] # 获取文件名
    with open(filename,'wb+') as f:
        f.write(resp.content)
    num = random.randint(2,5)
    print(filename + "generate:",num)
    time.sleep(num)
    return filename

urls = ["http://pic27.nipic.com/20130320/8952533_092547846000_2.jpg",
        "http://pic19.nipic.com/20120212/9337475_104548381000_2.jpg",]

ex = futures.ThreadPoolExecutor(max_workers = 3)
res_iter = ex.map(download_img,urls)
type(res_iter)
for res in res_iter:
    print(res)

def cf(rs):
    print(rs.result())

# [ex.submit(download_img,url).add_done_callback(cf) for url in urls]
# for future in futures.as_completed(fu_tasks):
for url in urls:
    f = ex.submit(download_img,url)
    f.add_done_callback(cf)

 

标签:thread,get,python,Queue,队列,线程,import,多线程
From: https://www.cnblogs.com/zhml/p/17346040.html

相关文章

  • 如何在交互式环境中执行Python程序
    相信接触过Python的小伙伴们都知道运行Python脚本程序的方式有多种,目前主要的方式有:交互式环境运行、命令行窗口运行、开发工具上运行等,其中在不同的操作平台上还互不相同。今天,小编讲些Python基础的内容,以Windows下交互式环境为依托,演示Python程序的运行。一般来说,顺利安装Python......
  • 手把手教你使用Python网络爬虫获取菜谱信息
    今日鸡汤一腔热血勤珍重,洒去犹能化碧涛。/1前言/    在放假时,经常想尝试一下自己做饭,下厨房这个网址是个不错的选择。    下厨房是必选的网址之一,主要提供各种美食做法以及烹饪技巧。包含种类很多。    今天教大家去爬取下厨房的菜谱,保存在world文档,方便日后制作自......
  • 手把手教你用Python打造一款批量下载视频并能可视化显示下载进度的下载器
    今日鸡汤桃之夭夭,灼灼其华。/1前言/    平时宅在家的我们最爱做的事莫过于追剧了,但是有时候了,网络原因,可能会让你无网可上。这个时候那些好看的电视剧和电影自然是无法观看了,本期我们要讲的就是怎样下载这些视频。/2项目目标/    通过Python程序对所感兴趣的视频进行批量......
  • 手把手教你使用Python生成图灵智能小伙伴,实现工作助手/闲聊功能
    /1前言/在家闲着,做个小项目,基于Python,实现一个语聊小机器人,分享给大家。项目整体比较简单,官方文档介绍的非常详细,可快速上手。/2 目标/将图灵机器人放到桌面,实现工作助手/陪聊功能。/3 涉及的库/V1.0版本:requests、jsonV2.0版本:requests、json、selenium(实现功能:如图灵返回结果......
  • 一篇文章带你用Python网络爬虫实现网易云音乐歌词抓取
    前几天小编给大家分享了数据可视化分析,在文尾提及了网易云音乐歌词爬取,今天小编给大家分享网易云音乐歌词爬取方法。本文的总体思路如下:找到正确的URL,获取源码;利用bs4解析源码,获取歌曲名和歌曲ID;调用网易云歌曲API,获取歌词;将歌词写入文件,并存入本地。本文的目的是获取网易云......
  • C++ - 多线程之初识多线程
    1.认识多线程传统的C++(C++11之前)中并没有引入线程这个概念,在C++11出来之前,如果我们想要在C++中实现多线程,需要借助操作系统平台提供的API,比如Linux的<pthread.h>,或者windows下的<windows.h>。C++11提供了语言层面上的多线程,包含在头文件<thread>中。它解决了跨平台的问题,提供......
  • 关于python爬虫解析的问题
    在进行Python爬虫解析时,需要注意以下事项:1、良好的网站使用协议:需要遵守网站的robots.txt文件,以确保你的爬虫程序不会将网站拦截下来。2、编码问题:需要正确设置HTTP头和解析器的编码,以确保爬虫程序能够正确地解析网站的信息。3、数据解析:需要适当地处理HTML文档中的标签,以便从......
  • python变量名规则&大小写敏感
    1.变量名由英文字母、下划线_或数字组成(不能包含空格、%、-、*、/、&、^等),并且第一个字符必须是英文字母或下划线。 2.变量名不能是Python关键字。(关键字指的是Python本身“已经在使用”的名字,Python已经占用了这些名字,所以我们不能用)常见的关键字:True False None(注意......
  • Python time 库常用函数
    time模块中时间表现的格式主要有三种:timestamp时间戳,时间戳表示的是从1970年1月1日00:00:00开始按秒计算的偏移量struct_time时间元组,共有九个元素组。formattime格式化时间,已格式化的结构使时间更具可读性。包括自定义格式和固定格式。使用time库前先用import导......
  • python3-hex
    hex函数,参数可以是一个int整数或一个bytes类型元素,转为0x的十六进制字符串形式withopen(file='J:/新建文本文档.txt',mode='rb')asf:s=f.read()print(type(s),s)result=''foriins:result+=hex(i)print(result)<class'......