• python学习04多线程


    1、线程与进程基本概念
    2、同步与异步
    3、并发与并行
    当用户在操作系统中启动某一个程序中,启动了至少一个进程,程序是一种静态资源实体,只是一系列代码。
    进程是动态的,当操作系统将程序数据载入内存时,创建一个动态实体,对各种资源进行操作。

    程序(静态) + 数据集 = 进程(运行时)
    不同进程之间不共享内存,一个进程包含至少一个或多个线程
    多个线程之间共享一个进程的内存,没有控制好,容易出现竞争状态,为了避免这种状态,出现互斥锁、信号量等机制

    互斥锁是指一个线程使用某一内存空间会获得的一把锁,使用锁将内存空间锁起来,其他线程只有等当前线程使用完毕并将锁
    释放,才能使用该内存空间中的资源。
    信号量用来指定某一内存空间通常可以被多少个线程使用。如当信号量为4时,内存空间中最多能同时存在4个线程,某个线程操作完
    内存空间中的资源后,信号量会自增1,允许其他线程进入到该内存空间

    同步与异步

    同步是指不同程序单元为了完成某个任务通过某种方式协调一致,异步是指不需要协调也可独立完成。

    ‘’’
    并发是指有限物理资源尽可能处理多个任务
    ‘’’

    from flask import Flask
    import time
    app = Flask(__name__)
    def longtime(s):
        time.sleep(s)
    
    @app.route('/index')
    
    def index():
        longtime(10)
        return 'hello sync flask'
    if __name__ == '__main__':
        app.run()
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13

    #通过性能池实现

    import time
    from concurrent.futures import ThreadPoolExecutor
    from flask import Flask
    executor = ThreadPoolExecutor(2)#创建线程池大小为2
    app = Flask(__name__)
    def longtime(s):
        time.sleep(s)
    @app.route('/index')
    def index():
        executor.submit(longtime,10)
        return 'hello async flask'
    
    if __name__ == '__main__':
        app.run()
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14

    ‘’’
    在python中有三种使用线程的方式,分别是thread、threading、ThreadPoolExecutor
    threading 有两种方式创建线程
    1、创建threading.Thread实例,将需要被线程执行的函数传入该实例
    2、创建一个类,继承于threading.Thread,重写run方法
    ‘’’

    import time
    import threading
    
    def longTime(s):
        time.sleep(s)
    
    def main():
        t = threading.Thread(target=longTime,args=[10])
        t.start()#start用于启动线程,在同一个线程中不能被多次调用
        t.join()#将主线程挂起,直到子线程运行结束
        print('Done')#子线程会执行10s,Done在10s后才打印
    
    if __name__ == '__main__':
        main()
    
    import time
    import threading
    
    class MyThread(threading.Thread):
        def __init__(self,func,args,tname = ''):
            #super (MyThread,self).__init__()
            super().__init__()
            self.tname = tname
            self.func = func
            self.args = args
    
        def run(self):
            self.func(*self.args)
    
    def longtime(s):
        time.sleep(s)
    
    def main():
        t = MyThread(longtime,(10,),longtime.__name__)
        t.start()
        t.join()
    
    if __name__ == '__main__':
        main()
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39

    #ThreadPoolExecutor使用
    #相比threading等模块,该模块通过submit返回一个future对象,通过它主线程(进程)中可以获取某一个
    #线程(进程)执行的状态或者某一任务执行的状态及返回值

    import time
    import random
    from concurrent.futures import ThreadPoolExecutor,as_completed
    def spider(url):
        '''
        爬虫方法
        :param url:
        :return:
        '''
        time.sleep(random.randint(1,5))
        print(f'crawl task {url} finished')
        return url
    
    #创建一个最大容纳数量为5的线程池
    with ThreadPoolExecutor(max_workers=5) as executor:
        urls = ['https://abc.com','https://efg.com','https://hij.com','https://klm.com'
                ,'https://nop.com','https://rsz.com']
        all_task = []
        for url in urls:#将任务提交到线程池
            task = executor.submit(spider,url)
            #将任务添加到对象列表
            all_task.append(task)
        #阻塞,获得任务完成后的返回值
        for future in as_completed(all_task):
            result = future.result()
            print(f'result:{result}')
        print('main_finished')
    '''
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28

    as_completed()方法是一个生成器,在没有完成任务的时候,会一直阻塞,除非设置了timeout
    当有某个任务完成的时候,会yield这个任务,就能执行for循环下的语句,然后继续阻塞,循环到所有的任务结束
    同时,先完成的任务会返回给主线程
    ‘’’

  • 相关阅读:
    时序资料汇总:模型和常见库对比
    【python】python面向对象——类的使用
    贤鱼的刷题日常--P1665 正方形计数--题目详解
    Zookeeper
    自动化测试平台设计与实现详解
    并发编程知识总结
    基于模糊控制算法的快速反射镜 系统扰动抑制
    Compose Desktop 使用中的几个问题(分平台加载资源、编写Gradle 任务下载平台资源、桌面特有组件、鼠标&键盘事件)
    信息系统项目管理师必背核心考点(七十一)审计Agent类型
    【面试题】 经典但依然超难做的 前端面试题 (值得收藏)
  • 原文地址:https://blog.csdn.net/mitudeniu/article/details/126474911