zoukankan      html  css  js  c++  java
  • 多线程与线程池

    多线程

    1,GIL全局解释器锁

    1. python GIL:(Global Interpret Lock)全局解释器锁
    2. CPython解释器自动加载GIL锁,基于单核CPU的GIL锁,为了保证数据的安全,单个进程的多线程不能利用多核,即可以并发,但是不能并行,多个进程可以并发,并行
    3. JPython,PYPY没有GIL锁
    4. 进入多核时代,GIL锁则成了python的一个弱点
    5. 以为CPython解释器所有的业务逻辑都是围绕单个线程实现的,去掉这个GIL锁,几乎不可能

    2,GIL与lock 的区别

    1. 相同点:都是互斥锁,
    2. 不同点:
      1. GIL是全局解释器锁,保护的是解释器内部的资源数据安全
      2. GIL锁的上锁和释放无序手动操作
      3. Lock:自己代码中定义的互斥锁,保护进程中的资源数据安全,需手动加锁,手动释放

    密集型,IO密集型的效率

    1,计算密集型:

    1. 多进程的并发并行效率高

    2. from threading import Thread
      from multiprocessing import Process
      import time
      import random
      # # 计算密集型: 单个进程的多线程并发 vs 多个进程的并发并行
      #
      # def task():
      #     count = 0
      #     for i in range(10000000):
      #         count += 1
      #
      #
      # if __name__ == '__main__':
      #
      #     # 多进程的并发,并行
      #     # start_time = time.time()
      #     # l1 = []
      #     # for i in range(4):
      #     #     p = Process(target=task,)
      #     #     l1.append(p)
      #     #     p.start()
      #     #
      #     # for p in l1:
      #     #     p.join()
      #     #
      #     # print(f'执行效率:{time.time()- start_time}')  # 3.1402080059051514
      #
      #     # 多线程的并发
      #     # start_time = time.time()
      #     # l1 = []
      #     # for i in range(4):
      #     #     p = Thread(target=task,)
      #     #     l1.append(p)
      #     #     p.start()
      #     #
      #     # for p in l1:
      #     #     p.join()
      #     #
      #     # print(f'执行效率:{time.time()- start_time}')  # 4.5913777351379395
      

    2,IO密集型:

    1. 单个进程的多线程的多线程的并发效率高

    2. def task():
          count = 0
          time.sleep(random.randint(1,3))
          count += 1
      
      # if __name__ == '__main__':
      
      # 多进程的并发,并行
      #     start_time = time.time()
      #     l1 = []
      #     for i in range(50):
      #         p = Process(target=task,)
      #         l1.append(p)
      #         p.start()
      #
      #     for p in l1:
      #         p.join()
      #
      #     print(f'执行效率:{time.time()- start_time}')  #  8.000000000
      
      # 多线程的并发
      #     start_time = time.time()
      #     l1 = []
      #     for i in range(50):
      #         p = Thread(target=task,)
      #         l1.append(p)
      #         p.start()
      #
      #     for p in l1:
      #         p.join()
      #
      #     print(f'执行效率:{time.time()- start_time}')  # 3.0294392108917236
      

    多线程实现socket通信

    1. 多线程的存在实现了socket真正的通信

    2. 服务端:

      1. import socket
        from threading import Thread
        
        
        def is_accept():
            server = socket.socket()
            server.bind(('127.0.0.1',8848))
            server.listen(5)
            while 1:
                conn,addr = server.accept()
                t = Thread(target=communicate, args=(conn,addr))
                t.start()
        
        
        def communicate(conn,addr):
            while 1:
                try:
                    from_client_data = conn.recv(1024)
                    print(f'来自{addr}客户端的消息:{from_client_data.decode("utf-8")}')
                    to_client_data = input('>>>>>>')
                    conn.send(to_client_data.encode('utf-8'))
                except ConnectionError:
                    break
            conn.close()
        
        
    3. 客户端

      1. import socket
        client = socket.socket()
        client.connect(('127.0.0.1', 8848))
        while 1:
            to_client_data = input('>>>>>>').strip()
            client.send(to_client_data.encode('utf-8'))
            from_client_data = client.recv(1024)
            print(f'来自服务端的消息:{from_client_data.decode("utf-8")}')
        client.close()
        

    进程池,线程池

    1. python标准模块:concurrent.futures———并发未来

      • concurent.future模块需要了解的
        1.concurent.future模块是用来创建并行的任务,提供了更高级别的接口,
        为了异步执行调用
        2.concurent.future这个模块用起来非常方便,它的接口也封装的非常简单
        3.concurent.future模块既可以实现进程池,也可以实现线程池
        4.模块导入进程池和线程池
        from  concurrent.futures import ProcessPoolExecutor,ThreadPoolExecutor
        还可以导入一个Executor,但是你别这样导,这个类是一个抽象类
        抽象类的目的是规范他的子类必须有某种方法(并且抽象类的方法必须实现),但是抽象类不能被实例化
        5.
          p = ProcessPoolExecutor(max_works)对于进程池如果不写max_works:默认的是cpu的数目,默认是4个
          p = ThreadPoolExecutor(max_works)对于线程池如果不写max_works:默认的是cpu的数目*5
        6.如果是进程池,得到的结果如果是一个对象。我们得用一个.get()方法得到结果
          但是现在用了concurent.future模块,我们可以用obj.result方法
          p.submit(task,i)  #相当于apply_async异步方法
          p.shutdown()  #默认有个参数wite=True (相当于close和join)
        
    2. 进程池:就是在一个进程内控制一定个数的线程

    3. 基于concurrent.futures模块的进程池和线程池,他们的同步执行和异步执行是一样

    希望你眼眸有星辰,心中有山海,从此以梦为马,不负韶华
  • 相关阅读:
    意外发现在调用Activator.CreateInstance的时候在构造函数处加断点居然可以~~
    手机操作系统
    读取Excel文件到DataSet
    支持mrp软件的手机(MTK手机)检测
    如何查看手机系统版本
    .NET进度条用例
    dos命令导出指定类型的文件列表
    FTP上传下载 FTP操作类 FTPHelper 异步上传 递归创建文件文件夹
    批量删除GridView(DataGrid)选中项
    sql判断临时表是否存在
  • 原文地址:https://www.cnblogs.com/daviddd/p/12034425.html
Copyright © 2011-2022 走看看