如何在 Grails 的线程中中断 HttpUrlConnection?
How to interrupt HttpUrlConnection in a thread in Grails?
我有一个线程可以打开 url 连接。当我想中断线程时遇到问题。不会抛出中断异常。
此代码在我的线程中运行
public void run() {
try {
final HttpURLConnection connection =new URL(url).openConnection()
connection.setReadTimeout(600000)
connection.setRequestMethod("POST")
connection.outputStream.withWriter { Writer writer ->
writer << requestxml
} catch (InterruptedException ie) {
println "interrupted"
} catch (Exception e) {
println "other error"
}
}
当我停止线程 theThread.interrupt() 时,请求不会停止。
当我使用一些伪代码(如 while(true) Thread.sleep(500) 时,中断工作正常。
我做错了什么?
中断线程的一个技巧是切断对作者的输入。这个例子说明了这个概念:
class RandomByteArrayInputStream extends InputStream {
def rand = new Random()
def isClosed = false
int read() {
if(isClosed) {
-1
} else {
rand.nextInt((90 - 65) + 1) + 65;
}
}
void close() {
isClosed = true
}
}
def input = new RandomByteArrayInputStream()
def output = new ByteArrayOutputStream()
println 'Starting background thread.'
def t = Thread.start {
output.withWriter {w ->
w << input
}
println 'Oh darn, ran out of input.'
}
println 'Sleeping...'
Thread.currentThread().sleep(5000)
println 'Awake! Closing input stream.'
input.close()
println 'Done'
在上面的例子中,RandomByteArrayInputStream 模拟了一个大的(实际上是无穷无尽的)数据源。休眠后,主线程关闭RandomByteArrayInputStream,导致writer停止写入,导致线程写完停止。
虽然 HttpURLConnection 超时起到一定作用,但可以使用类似的概念来中断写入此类连接:
class ClosableByteArrayInputStream extends ByteArrayInputStream {
def isClosed = false
public ClosableByteArrayInputStream(String string) {
super(string as byte[])
}
int read() {
isClosed ? -1 : super.read()
}
void close() {
isClosed = true
}
}
class MyThread extends Thread {
private InputStream inputStream
def url
def requestxml
public void run() {
final HttpURLConnection connection = url.openConnection()
connection.setReadTimeout(600000)
connection.setRequestMethod("POST")
connection.doOutput = true
inputStream = new ClosableByteArrayInputStream(requestxml)
connection.outputStream.withWriter { Writer writer ->
writer << inputStream
}
}
public void interrupt() {
inputStream?.close()
super.interrupt()
}
}
def t = new MyThread()
t.url = 'URL GOES HERE'.toURL()
t.requestxml = 'DATA GOES HERE'
t.start()
// Do whatever...
t.interrupt()
此处,使用 Thread 的子类而不是 Runnable 的实现,以便 interrupt 方法可以关闭从 XML 数据创建的输入流。
注意:我创建了 ClosableByteArrayInputStream,因为在 ByteArrayInputStream 上调用 close 方法没有任何效果。
我有一个线程可以打开 url 连接。当我想中断线程时遇到问题。不会抛出中断异常。
此代码在我的线程中运行
public void run() {
try {
final HttpURLConnection connection =new URL(url).openConnection()
connection.setReadTimeout(600000)
connection.setRequestMethod("POST")
connection.outputStream.withWriter { Writer writer ->
writer << requestxml
} catch (InterruptedException ie) {
println "interrupted"
} catch (Exception e) {
println "other error"
}
}
当我停止线程 theThread.interrupt() 时,请求不会停止。 当我使用一些伪代码(如 while(true) Thread.sleep(500) 时,中断工作正常。
我做错了什么?
中断线程的一个技巧是切断对作者的输入。这个例子说明了这个概念:
class RandomByteArrayInputStream extends InputStream {
def rand = new Random()
def isClosed = false
int read() {
if(isClosed) {
-1
} else {
rand.nextInt((90 - 65) + 1) + 65;
}
}
void close() {
isClosed = true
}
}
def input = new RandomByteArrayInputStream()
def output = new ByteArrayOutputStream()
println 'Starting background thread.'
def t = Thread.start {
output.withWriter {w ->
w << input
}
println 'Oh darn, ran out of input.'
}
println 'Sleeping...'
Thread.currentThread().sleep(5000)
println 'Awake! Closing input stream.'
input.close()
println 'Done'
在上面的例子中,RandomByteArrayInputStream 模拟了一个大的(实际上是无穷无尽的)数据源。休眠后,主线程关闭RandomByteArrayInputStream,导致writer停止写入,导致线程写完停止。
虽然 HttpURLConnection 超时起到一定作用,但可以使用类似的概念来中断写入此类连接:
class ClosableByteArrayInputStream extends ByteArrayInputStream {
def isClosed = false
public ClosableByteArrayInputStream(String string) {
super(string as byte[])
}
int read() {
isClosed ? -1 : super.read()
}
void close() {
isClosed = true
}
}
class MyThread extends Thread {
private InputStream inputStream
def url
def requestxml
public void run() {
final HttpURLConnection connection = url.openConnection()
connection.setReadTimeout(600000)
connection.setRequestMethod("POST")
connection.doOutput = true
inputStream = new ClosableByteArrayInputStream(requestxml)
connection.outputStream.withWriter { Writer writer ->
writer << inputStream
}
}
public void interrupt() {
inputStream?.close()
super.interrupt()
}
}
def t = new MyThread()
t.url = 'URL GOES HERE'.toURL()
t.requestxml = 'DATA GOES HERE'
t.start()
// Do whatever...
t.interrupt()
此处,使用 Thread 的子类而不是 Runnable 的实现,以便 interrupt 方法可以关闭从 XML 数据创建的输入流。
注意:我创建了 ClosableByteArrayInputStream,因为在 ByteArrayInputStream 上调用 close 方法没有任何效果。