You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何用ThreadPoolExecutor指定单线程执行get_cookie避免JIRA重复登录?

解决方案

问题核心

原代码里的cookie和cookie_time是全局变量,线程间没有同步机制,导致多个线程能同时通过过期判断,进而重复执行get_cookie(),触发多次登录操作。

方案1:用线程锁保护cookie更新逻辑

这是最直接的修复方式,通过threading.Lock把cookie检查和更新的逻辑变成原子操作,确保同一时间只有一个线程能执行刷新动作,其他线程会等待锁释放后再检查,此时cookie已经更新完成,不会重复刷新。

修改后的代码示例:

import concurrent.futures as fs
import time
import threading

# 初始化锁、cookie和时间
cookie_lock = threading.Lock()
cookie = get_cookie()
cookie_time = time.time()

page_size = 1000
total_num_issues = 100000

def safe_refresh_cookie():
    global cookie, cookie_time
    # 二次检查,防止等待锁的线程重复刷新
    if time.time() - cookie_time > 300:
        cookie = get_cookie()
        cookie_time = time.time()

with fs.ThreadPoolExecutor(max_workers=30) as ex:
    future_list = []
    for start_at in range(0, total_num_issues + 1, page_size):
        # 加锁执行cookie检查和刷新
        with cookie_lock:
            safe_refresh_cookie()
        extra_params = {"startAt": start_at, "maxResults": page_size}
        future_list.append(ex.submit(send_request, url, session, {**extra_params}))
    for future in fs.as_completed(future_list):
        issues += future.result()["issues"]

方案2:指定单个线程专门负责cookie刷新

可以启动一个后台线程,定时检查cookie有效期并提前自动刷新,业务线程完全不用处理cookie的问题,直接使用全局的有效cookie即可。

代码示例:

import concurrent.futures as fs
import time
import threading
import atexit

cookie = get_cookie()
cookie_time = time.time()
stop_refresh = threading.Event()

def cookie_refresher():
    global cookie, cookie_time
    while not stop_refresh.is_set():
        # 提前10秒刷新,避免刚好过期时业务线程出错
        time_until_expire = 300 - (time.time() - cookie_time)
        if time_until_expire <= 10:
            cookie = get_cookie()
            cookie_time = time.time()
        # 每隔10秒检查一次
        time.sleep(10)

# 启动后台刷新线程(设为守护线程,主程序退出时自动终止)
refresh_thread = threading.Thread(target=cookie_refresher, daemon=True)
refresh_thread.start()

# 程序退出时主动停止刷新线程,避免资源泄漏
atexit.register(lambda: stop_refresh.set())

page_size = 1000
total_num_issues = 100000

with fs.ThreadPoolExecutor(max_workers=30) as ex:
    future_list = []
    for start_at in range(0, total_num_issues + 1, page_size):
        extra_params = {"startAt": start_at, "maxResults": page_size}
        future_list.append(ex.submit(send_request, url, session, {**extra_params}))
    for future in fs.as_completed(future_list):
        issues += future.result()["issues"]

注意事项

  • 方案1的锁会带来轻微性能开销,但对于JIRA请求这类IO密集型任务,影响几乎可以忽略。
  • 方案2要确保后台线程能被正确终止,避免程序退出后残留线程。
  • 无论用哪种方案,要保证send_request函数使用的是最新的全局cookie,如果是通过参数传递,需确保提交任务时传入的是当前最新值。

内容的提问来源于stack exchange,提问作者Saguro

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.21 10:02:03