2

我有以下代码:

public class Net {
    public static void main(String[] args) {        
        Runnable task = new Runnable() {            
            @Override
            public void run() {
                String host = "http://example.example";
                try {
                    URL url = new URL(host);
                    StringBuilder builder = new StringBuilder();                    
                    HttpURLConnection con = (HttpURLConnection) url.openConnection();
                    try(BufferedReader in = new BufferedReader(new InputStreamReader(con.getInputStream()))) {  
                        String line;
                        while (null != (line = in.readLine())) builder.append(line);
                    }           
                    out.println("data: " + builder.length());
                    con.disconnect();
                } catch (MalformedURLException e) {
                    e.printStackTrace();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        };
        Thread thread = new Thread(task);
        thread.start();
        thread.interrupt();
    }
}

当主机出错时,此“con.getInputStream()”会阻塞线程。如何从另一个线程中断此代码?

4

4 回答 4

3

一般规则是从'外部'中断不可中断的线程,即

  • 线程等待连接/流 - 通过关闭连接。
  • 等待挂起进程完成的线程 - 通过终止进程。
  • (不是特别是这种情况)一个正在运行的长循环 - 通过引入一个从外部设置并不时在循环内部检查的布尔变量。
于 2013-10-31T13:00:35.733 回答
1

不幸的是,您不能中断被某些 I/O 操作阻塞的线程(除非您使用 NIO)。
您可能需要关闭读取线程已阻塞的流(由另一个线程)。
像这样的东西:

public class Foo implements Runnable{
private InputStream stream;
private int timeOut;
....
   public void run(){
    Thread.sleep(timeOut);
    if(<<ensure the victim thread still is stuck>>){
        stream.close();//this will throws an exception to the stuck thread.
    }
   }
....
}
于 2013-10-31T13:30:06.220 回答
1

用 设置超时值setReadTimeout。捕获SocketTimeoutExceptionif timeout expires 并以您想要的方式恢复或终止程序。

于 2013-10-31T12:46:27.090 回答
0

当主机出错时,此“con.getInputStream()”会阻塞线程。如何从另一个线程中断此代码?

这是一个常见问题解答。中断线程不会导致readLine(...)方法被中断。在这里引用我的回答:

我希望我的线程处理中断,但我无法捕获 InterruptedException,因为它是一个检查异常

重要的是要意识到 t.interrupt() 只设置线程中的中断位——它实际上并没有中断线程本身的处理。线程可以随时安全地中断。

因此,如果线程被阻塞,则无法中断线程readLine(...)。但是,您可以将循环更改为:

while (!Thread.currentThread().isInterrupted()) {
   String line = in.readLine();
   if (line == null) {
       break;
   }
   builder.append(line);
}

正如其他人所提到的,您可以关闭InputStream将导致readLine()抛出Exception.

于 2013-10-31T13:24:53.413 回答