V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
sadfQED2
V2EX  ›  Java

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

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

    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
    没法控制别人的代码,那就起进程,直接杀掉
    HuasLeung
        8
    HuasLeung  
       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   ·   实用小工具   ·   2038 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 23ms · UTC 16:15 · PVG 00:15 · LAX 08:15 · JFK 11:15
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.