A trick to interrupt the thread is to cut off the input to the writer. This example illustrates the concept:
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'
In the example above, the RandomByteArrayInputStream simulates a large (endless actually) source of data. After sleeping, the main thread closes the RandomByteArrayInputStream, which causes the writer to stop writing, which causes the thread to finish up and stop.
Although the HttpURLConnection timeout plays a part, a similar concept can be used to interrupt writing to such a connection:
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()
Here, a subclass of Thread is used instead of an implementation of Runnable so that the interrupt method can close the input stream created from the XML data.
Note: I created ClosableByteArrayInputStream because calling the close method on a ByteArrayInputStream has no effect.