我有一个访问网址的多线程程序。线程通过执行程序服务运行,当用户选择退出GUI时,程序会尝试通过调用executor.shutdownNow()
来中断线程。但是,程序关闭需要很长时间,因为许多线程在url.openStream()
调用中被阻止,并且由于这不会抛出InterruptedException
,所以到目前为止我已经在致电Thread.currentThread().isInterrupted()
之前和之后被强制检查。
我想知道在线程中断时是否有更好的方法来中断URL连接?否则,让程序尽快关闭的最佳方法是什么?
请注意,我不希望在连接上设置超时,因为我希望在程序运行时访问所有URL。
答案 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
实际上可能分别为HttpURLConnection
或HttpsURLConnection
。如果是这样,你很幸运。后者比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)
,这将强制所有线程死亡。