Java 如何中断线程并捕获可运行对象中的中断

Java 如何中断线程并捕获可运行对象中的中断,java,multithreading,Java,Multithreading,我有两个实现接口的对象,我分别执行它们。本质上,在Runnable对象的run()方法中,我执行了一些网络活动,其中包括调用在等待输入(来自网络)时阻塞的方法。请注意,我没有任何故意的暂停,即Thread.sleep()调用。任何暂停都是由对可能阻塞的方法的调用引起的 这些可运行对象由GUI控制,因此GUI界面和我希望向用户提供的一个功能是能够结束线程执行我的可运行对象,但我不知道如何做到这一点 一种明显的方法是调用Runnable对象线程的Thread.interrupt()方法,但是对Thr

我有两个实现接口的对象,我分别执行它们。本质上,在Runnable对象的
run()
方法中,我执行了一些网络活动,其中包括调用在等待输入(来自网络)时阻塞的方法。请注意,我没有任何故意的暂停,即
Thread.sleep()
调用。任何暂停都是由对可能阻塞的方法的调用引起的

这些可运行对象由GUI控制,因此GUI界面和我希望向用户提供的一个功能是能够结束线程执行我的可运行对象,但我不知道如何做到这一点

一种明显的方法是调用Runnable对象线程的Thread.interrupt()方法,但是对Thread方法的调用是如何传播到Runnable对象的呢?例如,我不能使用try-catch,似乎不允许在可运行对象中捕获
InterruptedException
;我的IDE(netbeans)抱怨在
run()
方法中从未抛出
InterruptedException

下面是我的代码,为简洁起见删去了。 在GUI线程的GUI代码中执行以下行:

digiSearch = new DigiSearch(hostIP,this);
digiSearchThread = new Thread(digiSearch);
digiSearchThread.start();
下面是我的Runnable类,我希望/需要在其中捕获其执行线程的中断

public class DigiSearch implements Runnable {

private String networkAdapterIP;
private DigiList digiList;

public DigiSearch (String ipAddress, DigiList digiList){
    networkAdapterIP = ipAddress;
    this.digiList = digiList;
}
@Override
public void run() {
    
    try{
        /*
 * Do some network and other activities here which includes calling some blocking methods.  However I would like to interrupt the run() method if possible by calling Thread.interrupt()
*/
                    
            
    }  catch (Exception ex){
       digiList.digiListException(ex);
    } catch (Throwable t){
       System.out.println("Search thread interrupted");
    }
}
}


有人能告诉我如何实现这一点,或者也许能解决我对中断线程的误解吗?

您有任何抛出
IOException
的阻塞方法吗?如果是这样,这可能是您的
InterruptedException
占位符。其中许多方法是在引入
InterruptedException
之前编写的,因此它们不是更新会破坏遗留代码的接口,而是将
InterruptedException
包装在
IOException


如果不是这样,你就有点被卡住了。例如,如果您编写了一个
Runnable
,它创建了一个只工作且从不休眠的无限循环,那么中断此线程不会导致
中断异常。
Runnable
负责定期检查
Thread.interrupted()

这里需要注意的几点:

1) 虽然我同意为用户提供停止线程执行的功能是有用的,但我建议考虑线程已经在执行的操作。是否可以回滚该操作?是否可以忽略该操作并停止执行

2) Thread.stop()和Thread.destroy()等是不推荐使用的方法()

那么,通常如何中断线程执行呢?输入可变状态变量

public class MyClass implements Runnable {
    private volatile boolean isAlive=true;

   /**
    * Request thread stop by calling requestThreadStop() externally.
    */
    public void requestThreadStop() {
        isAlive = false;
    }

    @Override
    public void run() {
        while(isAlive) {
            //Do All your thread work
            //if isAlive is modified, the next iteration will not happen
        }
    }
}
对于许多用例,上面的实现是有效的。但是,如果run()方法循环中的工作只是一次迭代,并且可能会阻塞相当长的时间,则用户必须等待操作完成

有没有一种方法可以在用户从GUI请求终止时几乎立即放弃线程的执行?大概为此,您必须探索使用线程池。使用ExecutorService,可以提供shutdown()和shutdownNow()方法的挂钩


为了避免重复,您可以从这个previoud stackoverflow帖子中找到关于线程池这个特性的更多信息

调用
Thread.interrupt()
然后抛出
抛出新的InterruptedException()调用interrupt()在何处以及在何处捕获异常(并重新抛出它)?要查看在Runnable.run()方法中抛出了什么异常(如果有),我为高级异常类放置了一个捕获。但是什么也没有发生,即在可运行对象中没有捕获任何异常。我不认为我想要在Java中实现的是可能的,唯一的方法就是如您所说的,不断检查标志。这是非常糟糕的,因为如果run()当前被阻止,那么标志将不会被检查。这可能只是Java中的一个失败?有可能得到线程当前正在执行的对象方法吗?看看这篇文章,它非常相似:据我所知不是这样,即使你这样做了,很有可能在确定类时,该类将不再执行。John B,我感谢您的回答,当然是正确的,但我决定将ar_blues的回答标记为我接受的答案,因为我认为其中包含了更多的信息,而且由于他/她是stackoverflow的新来者,我认为这是一个很好的回答,因为他们的回答值得表扬。我想你的好名声已经建立起来了:-)Thread.sleep不是不推荐的-你可能是指Thread.stop()。中断线程执行的标准方法是通过中断过程,这将包括Runnable定期检查中断状态。是的,我的run()方法不循环,它只有一个代码执行块(实际上它只是将数据文件上传到远程服务器)。立即停止上传不会有问题,事实上这是我想要的操作,也是我想要实现的。。这只是如何去实现它。你的评论很方便,我会调查你的建议。谢谢,我是说Thread.stop()。好像已经被编辑过了。谢谢。我倾向于@JohnB解决方案。只要您继续检查
Thread.interrupted
您可能甚至不需要该
isAlive
变量