如何在线程中断Java时停止URL连接

时间:2015-11-21 21:58:20

标签: java multithreading url

我有一个访问网址的多线程程序。线程通过执行程序服务运行,当用户选择退出GUI时,程序会尝试通过调用executor.shutdownNow()来中断线程。但是,程序关闭需要很长时间,因为许多线程在url.openStream()调用中被阻止,并且由于这不会抛出InterruptedException,所以到目前为止我已经在致电Thread.currentThread().isInterrupted()之前和之后被强制检查。

我想知道在线程中断时是否有更好的方法来中断URL连接?否则,让程序尽快关闭的最佳方法是什么?

请注意,我不希望在连接上设置超时,因为我希望在程序运行时访问所有URL。

4 个答案:

答案 0 :(得分:1)

如果查看URLConnection的Javadoc,它会给出一个提示:如果在URLConnection上调用getInputStream或getOutputStream,然后关闭其中任何一个流,它将关闭连接。如果你等待getInput / OutputStream调用,那么我认为不能做任何事情。但是如果你有流,关闭它(它将抛出一个IOException并释放在流上等待的所有线程)并且连接已经完成

仅供参考:我发现这种关闭InputStream的方法要么超时,要么只想停止处理是非常有效的,远比使用interrupt()

更有效。

答案 1 :(得分:0)

使用Apache HttpClient

最好的方法是使用Apache HttpClient而不是URLConnection。这是一种比URLConnection更先进的客户端,它更易于使用,并且可以中断。缺点是默认情况下它并未包含在所有Java环境中,因此它可能会导致您需要随软件一起提供额外的依赖性。如果没关系,那就去吧。

如果您必须坚持使用URLConnection

现在,网络上的网址通常使用HTTP或HTTPS,因此URLConnection实际上可能分别为HttpURLConnectionHttpsURLConnection。如果是这样,你很幸运。后者比URLConnection具有关键优势(见下文)。首先,您需要转换为HttpURLConnection。在URL中使用HTTP或HTTPS时,您可以安全地执行此操作。

HttpURLConnection conn = (HttpURLConnection) url.openConnection();

HttpURLConnection有一个额外的方法disconnect(),您现在可以使用它。调用此方法会导致getInputStream()或此类流上的read()次调用中阻止的任何线程抛出SocketException: Socket closed

conn.disconnect();

<强>买者
javadoc为disconnect()提供了相反的想法:

  

如果a,调用disconnect()方法可能会关闭底层套接字   此时持久连接处于空闲状态。

然而,我已经在Ubuntu和Android下的JDK1.8中对它进行了测试,它在两种环境中运行良好且完全相同,所以文档中的这句话实际上并不正确,也许它应该是不是真的,因为这是打断URLConnection的唯一方法。当客户端和服务器都表明他们可以保持连接时,甚至在没有&#34;否则空闲连接时,它甚至可以工作。

答案 2 :(得分:0)

我将使用 JAX-RS http客户端。它支持异步请求。原谅我使用Kotlin,但您可以用Java进行相同的操作。

//compile 'org.glassfish.jersey.core:jersey-client:2.0.1'
import javax.ws.rs.client.ClientBuilder

val th = Thread {
  val urlString = "http://long.running.page"
  val cli = ClientBuilder.newClient()
  val fut = cli.target(urlString).request().async().get()
  println(fut.get())
}
th.start()
println("wait")
Thread.sleep(3000)
println("interrupt")
th.interrupt()
th.join()

在对@DanielS答案发表评论后,我还使用HttpAsyncClients找到了asynchronous clients in Apache library的示例。似乎它支持中断,但不支持HttpClient类。

答案 3 :(得分:-2)

简单的回答是使用System.exit(0),这将强制所有线程死亡。