线程池使用

  1. from concurrent.futures import ThreadPoolExecutor, as_completed, wait, FIRST_COMPLETED
  2. from concurrent.futures import Future
  3. from multiprocessing import Pool
  4. #未来对象,task的返回容器
  5. #线程池, 为什么要线程池
  6. #主线程中可以获取某一个线程的状态或者某一个任务的状态,以及返回值
  7. #当一个线程完成的时候我们主线程能立即知道
  8. #futures可以让多线程和多进程编码接口一致
  9. import time
  10. def get_html(times):
  11. time.sleep(times)
  12. print("get page {} success".format(times))
  13. return times
  14. executor = ThreadPoolExecutor(max_workers=2)
  15. #通过submit函数提交执行的函数到线程池中, submit 是立即返回
  16. task1 = executor.submit(get_html, (3))
  17. task2 = executor.submit(get_html, (2))
  18. #要获取已经成功的task的返回
  19. # 1.wait
  20. executor = ThreadPoolExecutor(max_workers=2)
  21. urls = [3,2,4]
  22. all_task = [executor.submit(get_html, (url)) for url in urls]
  23. # return_when默认值是全部完成返回,可以增加超时时间参数
  24. wait(all_task, return_when=FIRST_COMPLETED)
  25. # 2.as_completed (submit + as_completed获取任务结果)
  26. ## all_task是多个任务
  27. ## 获取任务结果顺序: 谁先执行成功则返回谁的结果
  28. for future in as_completed(all_task):
  29. data = future.result()
  30. print("get {} page".format(data))
  31. # 3.map 提交任务 + 获取任务结果
  32. #通过executor的map获取已经完成的task的值
  33. ## urls是参数列表,交给get_html函数同时执行
  34. ## map返回结果顺序与urls参数列表顺序一致
  35. for data in executor.map(get_html, urls):
  36. print("get {} page".format(data))
  37. #done方法用于判定某个任务是否完成
  38. print(task1.done())
  39. print(task2.cancel()) ##取消任务
  40. time.sleep(3)
  41. print(task1.done())
  42. #result方法可以获取task的执行结果 #获取单个任务结果
  43. print(task1.result())
  44. # 使用案例1
  45. with ThreadPoolExecutor(max_workers=MAX_WORKERS) as executor:
  46. all_task=[executor.submit(main,ip,survival_ip_pool) for ip in ip_pool]
  47. ip_pool_fail=[] #失败ip池
  48. for future in as_completed(all_task,timeout=40):
  49. ipx,status = future.result()
  50. if not status:
  51. ip_pool_fail.append(ipx)
  52. # 使用案例2
  53. executor = ThreadPoolExecutor(max_workers=MAX_WORKERS) # 线程池为1000
  54. for ip in ip_pool:
  55. f = executor.submit(ping_ip, ip) # 提交即异步执行
  56. executor.shutdown() # 等待所有进程执行完毕后,关闭线程池。
  57. return ip_list
  58. # 使用案例3
  59. # 多线程执行main
  60. ip_pool_fail=[] #失败ip池
  61. executor=ThreadPoolExecutor(max_workers=MAX_WORKERS)
  62. all_task=[executor.submit(main,ip,survival_ip_pool,ip_pool_fail) for ip in ip_pool]
  63. wait(all_task,timeout=50) //阻塞50秒后不阻塞

gil说明

  1. gil global interpreter lock cpython
  2. python中一个线程对应于c语言中的一个线程
  3. gil使得同一个时刻只有一个线程在一个cpu上执行字节码, 无法将多个线程映射到多个cpu上执行
  4. gil会根据执行的字节码行数以及时间片释放gilgil在遇到io的操作时候主动释放
  5. import dis
  6. def add(a):
  7. a = a+1
  8. return a
  9. print(dis.dis(add))