多线程与线程池

Posted daviddd

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了多线程与线程池相关的知识,希望对你有一定的参考价值。

多线程

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模块的进程池和线程池,他们的同步执行和异步执行是一样

以上是关于多线程与线程池的主要内容,如果未能解决你的问题,请参考以下文章

newCacheThreadPool()newFixedThreadPool()newScheduledThreadPool()newSingleThreadExecutor()自定义线程池(代码片段

Java多线程-线程池的使用与线程总结(狂神说含代码)

线程池与并行度

线程池

阶段1 语言基础+高级_1-3-Java语言高级_05-异常与多线程_第5节 线程池_2_线程池的代码实现

多线程编程学习笔记——线程池