简单线程池:
  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()