线程池使用
from concurrent.futures import ThreadPoolExecutor, as_completed, wait, FIRST_COMPLETED
from concurrent.futures import Future
from multiprocessing import Pool
#未来对象,task的返回容器
#线程池, 为什么要线程池
#主线程中可以获取某一个线程的状态或者某一个任务的状态,以及返回值
#当一个线程完成的时候我们主线程能立即知道
#futures可以让多线程和多进程编码接口一致
import time
def get_html(times):
time.sleep(times)
print("get page {} success".format(times))
return times
executor = ThreadPoolExecutor(max_workers=2)
#通过submit函数提交执行的函数到线程池中, submit 是立即返回
task1 = executor.submit(get_html, (3))
task2 = executor.submit(get_html, (2))
#要获取已经成功的task的返回
# 1.wait
executor = ThreadPoolExecutor(max_workers=2)
urls = [3,2,4]
all_task = [executor.submit(get_html, (url)) for url in urls]
# return_when默认值是全部完成返回,可以增加超时时间参数
wait(all_task, return_when=FIRST_COMPLETED)
# 2.as_completed (submit + as_completed获取任务结果)
## all_task是多个任务
## 获取任务结果顺序: 谁先执行成功则返回谁的结果
for future in as_completed(all_task):
data = future.result()
print("get {} page".format(data))
# 3.map 提交任务 + 获取任务结果
#通过executor的map获取已经完成的task的值
## urls是参数列表,交给get_html函数同时执行
## map返回结果顺序与urls参数列表顺序一致
for data in executor.map(get_html, urls):
print("get {} page".format(data))
#done方法用于判定某个任务是否完成
print(task1.done())
print(task2.cancel()) ##取消任务
time.sleep(3)
print(task1.done())
#result方法可以获取task的执行结果 #获取单个任务结果
print(task1.result())
# 使用案例1
with ThreadPoolExecutor(max_workers=MAX_WORKERS) as executor:
all_task=[executor.submit(main,ip,survival_ip_pool) for ip in ip_pool]
ip_pool_fail=[] #失败ip池
for future in as_completed(all_task,timeout=40):
ipx,status = future.result()
if not status:
ip_pool_fail.append(ipx)
# 使用案例2
executor = ThreadPoolExecutor(max_workers=MAX_WORKERS) # 线程池为1000
for ip in ip_pool:
f = executor.submit(ping_ip, ip) # 提交即异步执行
executor.shutdown() # 等待所有进程执行完毕后,关闭线程池。
return ip_list
# 使用案例3
# 多线程执行main
ip_pool_fail=[] #失败ip池
executor=ThreadPoolExecutor(max_workers=MAX_WORKERS)
all_task=[executor.submit(main,ip,survival_ip_pool,ip_pool_fail) for ip in ip_pool]
wait(all_task,timeout=50) //阻塞50秒后不阻塞
gil说明
gil global interpreter lock (cpython)
python中一个线程对应于c语言中的一个线程
gil使得同一个时刻只有一个线程在一个cpu上执行字节码, 无法将多个线程映射到多个cpu上执行
gil会根据执行的字节码行数以及时间片释放gil,gil在遇到io的操作时候主动释放
import dis
def add(a):
a = a+1
return a
print(dis.dis(add))