Java 如何强行停止一个线程? - V2EX
V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
sadfQED2
V2EX    Java

Java 如何强行停止一个线程?

  •  
  •   sadfQED2 2019-10-01 17:09:48 +08:00 9396 次点击
    这是一个创建于 2254 天前的主题,其中的信息可能已经有所发展或是发生改变。

    Google 前几页的文章都看过了,没找到什么好办法,特来请教各位,我目前写的部分相当于一个框架,我提供 2 个按钮,开始和停止,点击开始后新启一个线程执行别人的代码,点击停止后杀掉这个线程,我并不能控制别人代码里面都判断了 InterruptedException 异常,那这种情况下我有什么办法强行停止线程内的操作呢? Thread.stop()方法已经被移除了,好像没有替代的了?

    24 条回复    2019-10-03 18:50:52 +08:00
    wzwwzw
        1
    wzwwzw  
       2019-10-01 17:26:54 +08:00
    有 pid 么,交给操作系统杀掉。
    sadfQED2
        2
    sadfQED2  
    OP
       2019-10-01 17:46:52 +08:00
    @wzwwzw #1

    ```
    Thread thread = new Thread(){
    @Override
    public void run() {
    // 执行别人的代码
    }
    };
    thread.start();
    ```

    不行吧?核心代码是这样的。点击停止按钮,执行
    ```
    thread.stop();
    ```
    但现在问题是 stop 方法已经被移除了
    tachikomachann
        3
    tachikomachann  
       2019-10-01 17:48:37 +08:00 via Android
    Thread.stop() 之所以移除原因就是强制杀掉线程会有不可预料的错误。
    所以正确的做法是用类似信号量控制的方式,让线程安全退出。
    Macolor21
        4
    Macolor21  
       2019-10-01 17:50:05 +08:00
    class CustomThread implement Runnable{
    private boolean flag=true;
    @Override
    public void run() {
    while(flag){
    }
    }
    Macolor21
        5
    Macolor21  
       2019-10-01 17:52:07 +08:00
    @Macolor21 #4
    不小心发出去了,这是简单的信号量控制方法,不过对方的代码的执行不可控的话,只能等 gc?
    aguesuka
        6
    aguesuka  
       2019-10-01 18:26:49 +08:00 via Android
    最不差的方法可能是,用线程池,shutDownNow。如果能改接口,返回一个 Futrue,实现曲线。
    pwrliang
        7
    pwrliang  
       2019-10-01 18:27:48 +08:00 via Android
    没法控制别人的代码,那就起进程,直接杀掉
    BCy66drFCvk1Ou87
        8
    BCy66drFCvk1Ou87  
       2019-10-01 18:30:06 +08:00 via Android
    信号量 semaphore
    aguesuka
        9
    aguesuka  
       2019-10-01 18:33:22 +08:00 via Android
    如果中断异常中断不了,那就用进程 start 和 kill
    Takamine
        10
    Takamine  
       2019-10-01 18:59:25 +08:00 via Android
    用一个 SingleThreadPool 呢。
    Raymon111111
        11
    Raymon111111  
       2019-10-01 20:10:39 +08:00
    把别人的代码放在 while(true) 里跑, 然后来个状态位
    magiclz233
        12
    magiclz233  
       2019-10-01 20:47:58 +08:00
    stop()强行停止,不建议使用了,如果你确定你的代码不会导致死锁或者数据不一致什么的,可以直接用 stop,或者用 interrupt,还有就是给线程代码中加异常,触发异常的话就会自动跳出了。又或者加判断条件。不过不推荐
    sadfQED2
        13
    sadfQED2  
    OP
       2019-10-01 22:45:49 +08:00
    @Macolor21 #5 信号控制我当然知道啊,但是别人的逻辑并不确定,万一别人写个 while(true)呢。

    @Raymon111111 #11 别人的代码只是给我一个入口,只调用一次,并不是多次调用


    @magiclz233 #12 stop()已经移除了,强制杀死我也知道可能会出一些资源回收等等问题,但是因为没发控制别人的代码,所以必须得自己想办法出问题的时候保证能结束


    @aguesuka #6 @Takamine #10 我考虑下
    Raymon111111
        14
    Raymon111111  
       2019-10-01 23:29:27 +08:00
    @sadfQED2 想想应该确实是做不到的, while(true) 这种应该是无法打断的.
    helloSpringBoot
        15
    helloSpringBoot  
       2019-10-01 23:59:11 +08:00 via Android
    之前也想过这个问题,强行终止只有 stop,但是现在已经废弃,不推荐使用。
    其它只能是协作式终止,中断加 flag 标志一起使用。
    如果对方代码不响应中断,那没有安全的办法了。
    java 并发编程实战有一章专门讲了这个问题。
    momocraft
        16
    momocraft  
       2019-10-02 00:01:14 +08:00
    子进程可能比较容易
    coolcfan
        17
    coolcfan  
       2019-10-02 00:05:39 +08:00
    线程池的 shutdownNow()也不能停止正在进行的任务。
    lastpass
        18
    lastpass  
       2019-10-02 02:30:23 +08:00 via Android   1
    如果你写的这个框架与你的应用不是同一个进程。
    继承对方的执行主类,添加一个停止的监听器方法。此监听被触发时,直接 system.exit()
    sadfQED2
        19
    sadfQED2  
    OP
       2019-10-02 08:43:17 +08:00 via Android
    @lastpass 也不行,我是给别人提供一个回调函数,别人在回调函数里面写他的逻辑,在回调函数里面我并不知道他怎么写,他的主类是啥
    STRRL
        20
    STRRL  
       2019-10-02 10:48:42 +08:00
    和他明确的说明要做 InterruptedException, 写到和他交接的文档里面.
    yulon
        21
    yulon  
       2019-10-02 14:23:27 +08:00
    合作:让他改。
    逆向:系统 API,做好崩溃的打算。
    sadfQED2
        22
    sadfQED2  
    OP
       2019-10-02 16:34:09 +08:00
    @STRRL #20 嗯,好像确实没其他方法了,只有在文档里面加要求了


    @helloSpringBoot #15 安不安全无所谓,stop 已经没有了,不然我用 stop 就好了,我怕的是别人代码里面万一写个类似 while(true)的代码,跳不出来
    0xZhangKe
        23
    0xZhangKe  
       2019-10-03 11:41:00 +08:00
    用 flag 配合中断标志位。
    while(!stop){
    try{
    ...
    } catch(InteruptException e){
    if(stop) return;
    }
    }

    再向外部暴露一个停止线程方法:

    public void stop(){
    stop = true;
    yourThread.interrupt();
    }
    kaminic
        24
    kaminic  
       2019-10-03 18:50:52 +08:00 via Android
    很明显,提需求让对方加退出接口,同时做好内部资源的释放
    关于     帮助文档     自助推广系统     博客     API     FAQ     Solana     1350 人在线   最高记录 6679       Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 27ms UTC 16:57 PVG 00:57 LAX 08:57 JFK 11:57
    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