请教如何优雅的停止一个 Java 正在运行的方法 - V2EX
V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
请不要在回答技术问题时复制粘贴 AI 生成的内容
Gct012
V2EX    程序员

请教如何优雅的停止一个 Java 正在运行的方法

  •  
  •   Gct012 2023 年 7 月 20 日 3065 次点击
    这是一个创建于 952 天前的主题,其中的信息可能已经有所发展或是发生改变。

    如题,我有一个 java 应用,其中有一个方法需要调用 n 个 Sql 处理数据,其中某个 Sql 经常性会卡住不动( DB 原因)。业务那边希望我们前台可以有一个触发按钮,一旦这个方法执行时间过长(超过半小时),他们可以在界面上手动取消这个方法的运行(不是停止 Java 服务哈),一旦 DBA 那边处理完成后,前台界面可以重新触发调用这个方法。

    我目前想到的唯一的办法就是在每个调用 Sql 的代码块之前增加标志位,一旦标志位被设为 False 。方法就抛出异常不再执行之后的方法。但是这样还是得等慢的那个 Sql 执行完才行,请问还有其他更加代码侵入性小一点的方法么?

    19 条回复    2023-07-21 10:09:44 +08:00
    connor123
        1
    connor123  
       2023 年 7 月 20 日
    建议优化 SQL 。
    qping
        2
    qping  
       2023 年 7 月 20 日
    sql 不是有超时吗,设定一个合理的超时时间
    zhazi
        3
    zhazi  
       2023 年 7 月 20 日
    都这样了,还优雅呢…… 你这问题就不优雅
    NoKey
        4
    NoKey  
       2023 年 7 月 20 日
    你这个慢 sql ,如果 dba 那边要处理,应该会很快结束(或者异常);如果 dba 不处理,java 这一侧,看起来好像也没啥好办法能强行终止执行,不终止执行,再起一个,那容易出问题~
    koloonps
        5
    koloonps  
       2023 年 7 月 20 日
    mybatis 设置 defaultStatementTimeout
    kaf
        6
    kaf  
       2023 年 7 月 20 日
    orm 配置超时不就可以了
    crayygy
        7
    crayygy  
       2023 年 7 月 20 日
    正常来讲是有别的更好的方案的,就着你的方案来看,也许可以考虑放到一个新的 Thread 或者 Task 里面,然后 cancel 这个 task
    mmdsun
        8
    mmdsun  
       2023 年 7 月 20 日   1
    看你数据库驱动是否支持,PreparedStatement 有 cancel 这个可以真正取消。
    narakus
        9
    narakus  
       2023 年 7 月 20 日   1
    将业务逻辑交给线程池执行,其中另外再写一个中断指定线程等方法,
    在一开始程序启动的时候,直接调用启动线程池,因为是多线程形式的,因此其中有一个卡顿并不影响另外几个线程执行业务逻辑,
    如果需要返回结果,可以用带返回结果的线程来执行,超时可以提前返回,然后页面人工查询干预,干预的时候,页面点击了中断超时就可以调用中断指定线程的方法,
    然后释放这个线程到线程池

    需要注意的是做好并发控制

    以上方法不影响主程序的运行,只针对运行超时的线程采取措施
    另外建议优先考虑优化下 SQL
    28Sv0ngQfIE7Yloe
        10
    28Sv0ngQfIE7Yloe  
       2023 年 7 月 20 日
    感觉你这是个 XY problem 。

    (写完这句突然想到了耗子哥)
    wxlwsy
        11
    wxlwsy  
       2023 年 7 月 20 日
    解决问题的方向就错了. 要么都成功要么都失败. 执行一半途停止又不回滚.鬼知道会怎么样.
    githmb
        12
    githmb  
       2023 年 7 月 20 日
    请先思考一下如何中断下面的代码:

    for (;;) {}
    gaifanking
        13
    gaifanking  
       2023 年 7 月 20 日
    所以你的方法是执行了半小时还没返回吗 -,- 这种应该做成有状态的吧,提交就立即返回,给一个 token ;取消时把 token 传过来,java 这边调用数据库 api kill 掉 sql 。
    paranoiagu
        14
    paranoiagu  
       2023 年 7 月 20 日 via Android
    还要考虑并发吗?
    CoffeeY
        15
    CoffeeY  
       2023 年 7 月 20 日
    +1 ,建议线程池
    waterlaw
        16
    waterlaw  
       2023 年 7 月 21 日 via Android
    HB9527
        17
    HB9527  
       2023 年 7 月 21 日   1
    kill -9 ,非常优雅
    dongdong12345
        18
    dongdong12345  
       2023 年 7 月 21 日   2
    手动处理数据库连接。比如使用 mybatis 框架,手动获取 SqlSession 来执行数据库操作,包括 sqlSession.commit()和 sqlSession.rollback()手动控制事务,然后将你这个 SqlSession 保存在内存中,可以放到一个 Map 里,key 可以是这个任务的 ID ,value 可以是个实体类,包含 SqlSession 字段以及执行任务线程返回的 Future 。
    当在页面点击停止时,传入这个任务 ID ,在 Map 中根据任务 ID 找到对应的 SqlSession 和任务线程的 Future ,调用 session.close()释放连接,然后调用 Future 中的 cancel()方法取消任务。
    jorneyr
        19
    jorneyr  
       2023 年 7 月 21 日
    JDBC Statement 有 2 个方法: setQueryTimeout() 和 cancel() 可以解决这个问题。
    关于     帮助文档     自助推广系统     博客     API     FAQ     Solana     3015 人在线   最高记录 6679       Select Language
    创意工作者们的社区
    Wrld is powered by solitude
    VERSION: 3.9.8.5 24ms UTC 14:35 PVG 22:35 LAX 06:35 JFK 09:35
    Do have faith in what you're doing.
    ubao msn snddm index pchome yahoo rakuten mypaper meadowduck bidyahoo youbao zxmzxm asda bnvcg cvbfg dfscv mmhjk xxddc yybgb zznbn ccubao uaitu acv GXCV ET GDG YH FG BCVB FJFH CBRE CBC GDG ET54 WRWR RWER WREW WRWER RWER SDG EW SF DSFSF fbbs ubao fhd dfg ewr dg df ewwr ewwr et ruyut utut dfg fgd gdfgt etg dfgt dfgd ert4 gd fgg wr 235 wer3 we vsdf sdf gdf ert xcv sdf rwer hfd dfg cvb rwf afb dfh jgh bmn lgh rty gfds cxv xcv xcs vdas fdf fgd cv sdf tert sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf shasha9178 shasha9178 shasha9178 shasha9178 shasha9178 liflif2 liflif2 liflif2 liflif2 liflif2 liblib3 liblib3 liblib3 liblib3 liblib3 zhazha444 zhazha444 zhazha444 zhazha444 zhazha444 dende5 dende denden denden2 denden21 fenfen9 fenf619 fen619 fenfe9 fe619 sdf sdf sdf sdf sdf zhazh90 zhazh0 zhaa50 zha90 zh590 zho zhoz zhozh zhozho zhozho2 lislis lls95 lili95 lils5 liss9 sdf0ty987 sdft876 sdft9876 sdf09876 sd0t9876 sdf0ty98 sdf0976 sdf0ty986 sdf0ty96 sdf0t76 sdf0876 df0ty98 sf0t876 sd0ty76 sdy76 sdf76 sdf0t76 sdf0ty9 sdf0ty98 sdf0ty987 sdf0ty98 sdf6676 sdf876 sd876 sd876 sdf6 sdf6 sdf9876 sdf0t sdf06 sdf0ty9776 sdf0ty9776 sdf0ty76 sdf8876 sdf0t sd6 sdf06 s688876 sd688 sdf86