• Python全栈开发:线程代码实例


    #进程与线程的关系
    """
    多进程(主进程,子进程):
        优点:能同时利用多个CPU,进行多个操作,提高效率。
        缺点:耗费内存资源(进程要开辟内存空间),进程不是越多越好,CPU个数 = 进程个数。
        注意:进程创建内存空间,线程共享内存空间,进程里有全局解释器锁,进程中一次只应许一个线程被处理。
        使用场景:计算密集型适合多进程。
    多线程(主线程,子线程):
        优点:共享内存,IO操作时(不用CPU),创造并发操作(多个操作同时进行),提高效率。
        缺点:抢占资源,请求上下文切换非常耗时(线程处理切换后找到上次处理的地方),线程不是越多越好,视具体案例而定。
        注意:在计算机中,执行任务的最小单元就是线程。
        使用场景:IO密集型适合多线程。
    """
    """
    队列queue
        先进先出,一边放,另一边取
        可设置最大个数,get等待,get_nowait不等待
    """
    """
    使用线程
        1、创建线程
            import threading
            import time
            def f1():
                pass
            def f2(a1, a2):
                time.sleep(10)
                pass
            t = threading.Thread(target=f1, args=(11,22,33))
            t.start() # 线程开始跑,创建的是子线程
        2、线程锁
            防止出现脏数据,一个线程读取数据并对其加锁,CPU切换线程后其他线程不能读取数据,
        3、线程池
            Python内部没有提供线程池,需要自定义
    """
    import threading
    import time
    
    
    def f1():
        pass
    
    
    def f2(a1, a2):
        time.sleep(10)
        pass
    
    t1 = threading.Thread(target=f2, args=(11, 22))
    t1.setDaemon(True)  # 主线程是否等待子线程
    t1.start()  # 线程开始跑,创建的是子线程
    print("第一次等待中")
    t1.join(2)  # 主线程等待子线程多久,不加参数无限等待
    t2 = threading.Thread(target=f2, args=(11, 22))
    t2.setDaemon(True)
    t2.start()  # 线程开始跑,创建的是子线程
    print("第二次等待中")
    t2.join(2)  # 主线程等待子线程的执行的最多等待时间,超过时间,主线程继续执行下一部分
    t3 = threading.Thread(target=f2, args=(11, 22))
    t3.setDaemon(True)  # 主线程执行完(解释器执行代码),是否等待子线程执行完再关闭,True:不等待:False:等待。默认为False
    t3.start()  # 线程开始跑,创建的是子线程
    

      线程event

    #!/usr/bin/env python
    # -*- coding;utf-8 -*-
    """
        线程event
    """
    import threading
    import time
    
    def do(event):
        print("线程前半部分")
        event.wait()  # 阻塞(十字路口),红灯则等待,绿灯则继续执行
        print("线程后半部分")
    
    
    event_obj = threading.Event()
    
    for i in range(10):
        t = threading.Thread(target=do, args=(event_obj,))
        t.start()
    # 耗时十分钟
    # time.sleep(10)
    
    event_obj.clear()  # 让灯变红
    inp = input("请输入内容:>>>")
    if inp == "true":
        event_obj.set()  # 让灯变绿,线程就都可以继续执行
    

      线程数据共享

    #!/usr/bin/env python
    # -*- coding;utf-8 -*-
    """
        默认情况下线程数据不共享
        线程与线程之间数据可以共享
    """
    from threading import Thread
    li = []
    
    
    def foo(i):
        li.append(i)
        print("hello", li)
    
    if __name__ == "__main__":
        for i in range(10):
            t = Thread(target=foo, args=(i,))
            t.start()
    

      线程池

    1. 简单线程池
      #!/usr/bin/env python
      # -*- coding;utf-8 -*-
      """
          自定义线程池博客园教程地址
              http://www.cnblogs.com/wupeiqi/articles/4839959.html
      """
      import queue
      import threading
      import time
      
      class ThreadPool(object):
      
          def __init__(self, max_num=20):
              self.queue = queue.Queue(max_num)
              for i in range(max_num):
                  self.queue.put(threading.Thread)
      
          def get_thread(self):
              return self.queue.get()
      
          def add_thread(self):
              self.queue.put(threading.Thread)
      
      def func(i, arg):
          print(i)
          time.sleep(4)
          # 在队列中增加线程类
          arg.add_thread()
      
      if __name__ == "__main__":
          # 在队列中创建线程类
          pool = ThreadPool(10)
          for i in range(30):
              # 获得类
              thread = pool.get_thread()
              # 对象 = 类()
              ret = thread(target=func, args=(i, pool))
              ret.start()
    2. 高级线程池
      #!/usr/bin/env python
      # -*- coding;utf-8 -*-
      import threading
      import time
      import queue
      import contextlib
      StopEvent = object()
      
      class Threadpool(object):
      
          def __init__(self, max_num):
              self.max_num = max_num
              # 创建任务队列
              self.queue = queue.Queue()
              self.terminal = False
              # 表示真实创建的线程列表
              self.generate_list = []
              # 表示空闲的线程列表
              self.free_list = []
      
          def run(self, func, args, callback=None):
              """
              线程池执行一个任务
              :param func: 执行任务的函数
              :param args: 任务函数的参数(以元组形式存在的任务包,封装了几个参数)
              :param callback: 任务执行失败或者成功后执行的回调函数,回调函数有两个参数
              :return:
              """
              # 往任务队列里加任务
              w = (func, args, callback)
              self.queue.put(w)
              # 如果空闲线程等于零并且真实创建的线程数小于任务数
              if len(self.free_list) == 0 and len(self.generate_list) < self.max_num:
                  self.generate_thread()
      
          def generate_thread(self):
              """
              创建一个线程
              :return:
              """
              t = threading.Thread(target=self.call)
              t.start()
      
          def call(self):
              """
              循环去获取任务函数并执行任务函数
              :return:
              """
              current_thread = threading.current_thread()
              self.generate_list.append(current_thread)
              # 去任务并执行
              event = self.queue.get()
              while event != StopEvent:
                  # 如果是元组任务,解开任务包,执行任务
                  func, args, callback = event
      
                  try:
                      ret = func(*args)
                      success = True
                  except Exception as e:
                      success = False
                      ret = e
      
                  if callback is not None:
                      try:
                          callback(success, ret)
                      except Exception as e:
                          pass
                  with self.work_station(self.free_list, current_thread):
                      if self.terminal:
                          event = StopEvent
                      else:
                          event = self.queue.get()
      
              else:
                  self.generate_list.remove(current_thread)
      
          def close(self):
              # 中途终止线程
              num = len(self.generate_list)
              while num:
                  self.queue.put(StopEvent)
                  num -= 1
      
          def terminate(self):
              #  终止线程(不清空队列),线程一直在等待拿,程序不会退出
              """
              终止线程(清空队列)
                  while self.generate_list:
                      self.queue.put(StopEvent)
              """
              self.terminate = True
              max_num = len(self.generate_list)
              # self.queue.empty()
              while max_num:
                  max_num = len(self.generate_list)
                  max_num -= 1
              #self.queue.empty()
      
          @contextlib.contextmanager
          def work_station(self, station, val):
              station.append(val)
              try:
                  yield
              finally:
                  station.remove(val)
      
      def work(i):
          # time.sleep(3)
          print(i)
      
      pool = Threadpool(10)
      for i in range(50):
          pool.run(func=work, args=(i,), callback=None)
      
      # pool.terminate()
      pool.close()
    3. 绝版线程池
      #!/usr/bin/env python
      # -*- coding;utf-8 -*-
      """
          自定义线程池博客园教程地址
              http://www.cnblogs.com/wupeiqi/articles/4839959.html
      """
      import queue
      import threading
      import contextlib
      import time
      StopEvent = object()
      
      class ThreadPool(object):
      
          def __init__(self, max_num, max_task_num = None):
              if max_task_num:
                  self.q = queue.Queue(max_task_num)
              else:
                  self.q = queue.Queue()
              self.max_num = max_num
              self.cancel = False
              self.terminal = False
              self.generate_list = []
              self.free_list = []
      
          def run(self, func, args, callback=None):
              """
              线程池执行一个任务
              :param func: 任务函数
              :param args: 任务函数所需参数
              :param callback: 任务执行失败或成功后执行的回调函数,回调函数有两个参数1、任务函数执行状态;2、任务函数返回值(默认为None,即:不执行回调函数)
              :return: 如果线程池已经终止,则返回True否则None
              """
              if self.cancel:
                  return
              if len(self.free_list) == 0 and len(self.generate_list) < self.max_num:
                  self.generate_thread()
              w = (func, args, callback,)
              self.q.put(w)
      
          def generate_thread(self):
              """
              创建一个线程
              """
              t = threading.Thread(target=self.call)
              t.start()
      
          def call(self):
              """
              循环去获取任务函数并执行任务函数
              """
              current_thread = threading.currentThread()
              self.generate_list.append(current_thread)
      
              event = self.q.get()
              while event != StopEvent:
      
                  func, arguments, callback = event
                  try:
                      result = func(*arguments)
                      success = True
                  except Exception as e:
                      success = False
                      result = None
      
                  if callback is not None:
                      try:
                          callback(success, result)
                      except Exception as e:
                          pass
      
                  with self.worker_state(self.free_list, current_thread):
                      if self.terminal:
                          event = StopEvent
                      else:
                          event = self.q.get()
              else:
      
                  self.generate_list.remove(current_thread)
      
          def close(self):
              """
              执行完所有的任务后,所有线程停止
              """
              self.cancel = True
              full_size = len(self.generate_list)
              while full_size:
                  self.q.put(StopEvent)
                  full_size -= 1
      
          def terminate(self):
              """
              无论是否还有任务,终止线程
              """
              self.terminal = True
      
              while self.generate_list:
                  self.q.put(StopEvent)
      
              self.q.queue.clear()
      
          @contextlib.contextmanager
          def worker_state(self, state_list, worker_thread):
              """
              用于记录线程中正在等待的线程数
              """
              state_list.append(worker_thread)
              try:
                  yield
              finally:
                  state_list.remove(worker_thread)
      
      # How to use
      pool = ThreadPool(5)
      
      
      def callback(status, result):
          # status, execute action status
          # result, execute action return value
          pass
      
      def action(i):
          print(i)
      
      if __name__ == "__main__":
          for i in range(30):
              ret = pool.run(action, (i,), callback)
          time.sleep(0.01)  # 等待的时间xiao'l
          print(len(pool.generate_list), len(pool.free_list))
          print(len(pool.generate_list), len(pool.free_list))
          pool.close()  # 子线程结束时,主线程就结束,time.sleep后的内容可能没有结果
          # pool.terminate()
      

        

  • 相关阅读:
    大数据、数据挖掘在交通领域的应用
    浅谈 kubernetes service 那些事(上篇)
    Docker中搭建zookeeper集群
    【kudu pk parquet】runtime filter实践
    【大数据之数据仓库】选型流水记
    【大数据之数据仓库】安装部署GreenPlum集群
    【大数据之数据仓库】GreenPlum优化器对比测试
    【大数据之数据仓库】GreenPlum PK DeepGreen(TPCH)
    【大数据之数据仓库】HAWQ versus GreenPlum
    用 PS 调整服务器时间
  • 原文地址:https://www.cnblogs.com/nixingguo/p/6492827.html
Copyright © 2020-2023  润新知