The JDK docs say, that if a thread is interrupted that currently blocks in an io operation of an InterruptibleChannel, the channel is closed and a ClosedByInterruptException is thrown. However, i get a different behaviour when using a FileChannel:
public class Main implements Runnable {
public static void main(String[] args) throws Exception {
Thread thread = new Thread(new Main());
thread.start();
Thread.sleep(500);
thread.interrupt();
thread.join();
}
public void run() {
try {
readFile();
} catch (IOException ex) {
ex.printStackTrace();
}
}
private void readFile() throws IOException {
FileInputStream in = new FileInputStream("large_file");
FileChannel channel = in.getChannel();
ByteBuffer buffer = ByteBuffer.allocate(0x10000);
for (;;) {
buffer.clear();
// Thread.currentThread().interrupt();
int r = channel.read(buffer);
if (Thread.currentThread().isInterrupted()) {
System.out.println("thread interrupted");
if (!channel.isOpen())
System.out.println("channel closed");
}
if (r < 0)
break;
}
}
}
Here, when the thread is interrupted, the read() call returns normally even so the channel has been closed. No exception is thrown. This code prints "thread interrupted" and "channel closed", and then on the next call to read() it throws a ClosedChannelException.
I wonder wether this behaviour is allowed. As i understand the docs, the read() should either return normally and not close the channel or close the channel and throw ClosedByInterruptException. Returning normally and closing the channel does not seem right. The trouble for my application is, that i get an unexpected and seemingly unrelated ClosedChannelException somewhere else, when a FutureTask that does io gets cancelled.
Note: The ClosedByInterruptException will get thrown as expected, when the thread is already interrupted when entering the read().
I have seen this behaviour using the 64-Bit Server-VM (JDK 1.6.0 u21, Windows 7). Can anyone confirm this?