• 线程池


    简单线程池:
    1. #!/usr/bin/env python
    2. # Version = 3.5.2
    3. # __auth__ = '无名小妖'
    4. import queue
    5. import threading
    6. import time
    7. class ThreadPool:
    8. """
    9. 简易线程池类,缺陷:1.线程无法重用
    10. 2.初始线程最大化,可能导致浪费
    11. """
    12. def __init__(self, maxsize=5):
    13. """
    14. 通过队列实现线程池
    15. :param maxsize: 线程池最大值
    16. """
    17. self.maxsize = maxsize
    18. self._q = queue.Queue(maxsize)
    19. # 将线程类循环放入队列
    20. for i in range(maxsize):
    21. self._q.put(threading.Thread)
    22. def get_thread(self):
    23. """
    24. 从队列中取出线程类
    25. :return: 线程类
    26. """
    27. return self._q.get()
    28. def add_thread(self):
    29. """
    30. 放入类
    31. :return: none
    32. """
    33. self._q.put(threading.Thread)
    34. # 实例化线程池
    35. pool = ThreadPool()
    36. # 测试函数
    37. def task(a, p):
    38. print(a)
    39. time.sleep(1)
    40. p.add_thread()
    41. for i in range(100):
    42. t = pool.get_thread()
    43. t_obj = t(target=task, args=(i, pool))
    44. t_obj.start()


    优化线程池:
    1. #!/usr/bin/env python
    2. # Version = 3.5.2
    3. # __auth__ = '无名小妖'
    4. import queue
    5. import threading
    6. import contextlib
    7. import time
    8. # 静态字段,线程停止标记
    9. StopEvent = object()
    10. class ThreadPool(object):
    11. def __init__(self, max_num, max_task_num = None):
    12. """
    13. :param max_num: 线程池大小
    14. :param max_task_num: 任务数量,默认无限
    15. """
    16. if max_task_num:
    17. self.q = queue.Queue(max_task_num)
    18. else:
    19. self.q = queue.Queue()
    20. self.max_num = max_num
    21. self.cancel = False
    22. self.terminal = False
    23. self.generate_list = [] # 当前创建的线程
    24. self.free_list = [] # 当前空闲的线程
    25. def run(self, func, args, callback=None):
    26. """
    27. 线程池执行一个任务
    28. :param func: 任务函数
    29. :param args: 任务函数所需参数
    30. :param callback: 任务执行失败或成功后执行的回调函数,回调函数有两个参数1、任务函数执行状态;
    31. 2、任务函数返回值(默认为None,即:不执行回调函数)
    32. :return: 如果线程池已经终止,则返回True否则None
    33. """
    34. if self.cancel:
    35. return
    36. # 判断 如果没有空闲线程 并且 已经创建的线程小于最大线程数,创建新线程
    37. if len(self.free_list) == 0 and len(self.generate_list) < self.max_num:
    38. self.generate_thread()
    39. # 把任务放队列
    40. w = (func, args, callback,)
    41. self.q.put(w)
    42. def generate_thread(self):
    43. """
    44. 创建一个线程,并执行call方法
    45. """
    46. t = threading.Thread(target=self.call)
    47. t.start()
    48. def call(self):
    49. """
    50. 循环去获取任务函数并执行任务函数
    51. """
    52. current_thread = threading.currentThread()
    53. self.generate_list.append(current_thread)
    54. event = self.q.get() # 取任务
    55. while event != StopEvent: # 循环执行任务
    56. func, arguments, callback = event
    57. try:
    58. result = func(*arguments) # 任务函数
    59. success = True
    60. except Exception as e:
    61. success = False
    62. result = None
    63. if callback is not None:
    64. try:
    65. callback(success, result) # 回调函数
    66. except Exception as e:
    67. pass
    68. # 执行完任务,将线程置为空闲
    69. with self.worker_state(self.free_list, current_thread):
    70. if self.terminal:
    71. event = StopEvent
    72. else:
    73. event = self.q.get()
    74. else:
    75. self.generate_list.remove(current_thread)
    76. def close(self):
    77. """
    78. 执行完所有的任务后,所有线程停止
    79. """
    80. self.cancel = True
    81. full_size = len(self.generate_list)
    82. while full_size:
    83. self.q.put(StopEvent) # 将终止标识放入队列
    84. full_size -= 1
    85. def terminate(self):
    86. """
    87. 无论是否还有任务,终止线程
    88. """
    89. self.terminal = True
    90. while self.generate_list:
    91. self.q.put(StopEvent)
    92. self.q.queue.clear()
    93. """ 经常使用到的with场景是(打开文件进行文件处理,
    94. 然后隐式地执行了文件句柄的关闭,同样适合socket之类的,这些类都提供了对with的支持)
    95. contextlib是为了加强with语句,提供上下文机制的模块,它是通过Generator实现的。
    96. contextlib中的contextmanager作为装饰器来提供一种针对函数级别的上下文管理机制 ."""
    97. @contextlib.contextmanager
    98. def worker_state(self, state_list, worker_thread):
    99. """
    100. 用于记录线程中正在等待的线程数
    101. """
    102. state_list.append(worker_thread)
    103. try:
    104. yield
    105. finally:
    106. state_list.remove(worker_thread)
    107. # 实例化线程池
    108. pool = ThreadPool(3)
    109. def callback(status, result):
    110. # status, execute action status
    111. # result, execute action return value
    112. if status == True:
    113. print('Completed!')
    114. def action(i):
    115. print(i)
    116. for i in range(30):
    117. ret = pool.run(action, (i,), callback)
    118. time.sleep(5)
    119. print(len(pool.generate_list), len(pool.free_list))
    120. pool.close()
    121. # pool.terminate()





  • 相关阅读:
    Redis计数信号量
    一台服务器能支撑多少个TCP连接
    Python常见字符编码间的转换
    浅谈HttpDNS
    用Python写的一个MySQL数据库监测系统
    用Python写的一个MySQL数据库监测系统
    how tomcat works(第九章)
    how tomcat works(第八章)
    how tomcat works(第八章)
    how tomcat works(第九章)
  • 原文地址:https://www.cnblogs.com/wumingxiaoyao/p/7047857.html
Copyright © 2020-2023  润新知