我只是在学习NIO,下面是我编写的测试阻塞NIO如何被中断的简短示例:
class TestBlockingNio {
private static final boolean INTERRUPT_VIA_THREAD_INTERRUPT = true;
/**
* Prevent the socket from being GC'ed
*/
static Socket socket;
private static SocketChannel connect(final int port) {
while (true) {
try {
final SocketChannel channel = SocketChannel.open(new InetSocketAddress(port));
channel.configureBlocking(true);
return channel;
} catch (final IOException ioe) {
try {
Thread.sleep(1000);
} catch (final InterruptedException ie) {
}
continue;
}
}
}
private static byte[] newBuffer(final int length) {
final byte buffer[] = new byte[length];
for (int i = 0; i < length; i++) {
buffer[i] = (byte) 'A';
}
return buffer;
}
public static void main(final String args[]) throws IOException, InterruptedException {
final int portNumber = 10000;
new Thread("Reader") {
public void run() {
try {
final ServerSocket serverSocket = new ServerSocket(portNumber);
socket = serverSocket.accept();
/*
* Fully ignore any input from the socket
*/
} catch (final IOException ioe) {
ioe.printStackTrace();
}
}
}.start();
final SocketChannel channel = connect(portNumber);
final Thread main = Thread.currentThread();
final Thread interruptor = new Thread("Inerruptor") {
public void run() {
System.out.println("Press Enter to interrupt I/O ");
while (true) {
try {
System.in.read();
} catch (final IOException ioe) {
ioe.printStackTrace();
}
System.out.println("Interrupting...");
if (INTERRUPT_VIA_THREAD_INTERRUPT) {
main.interrupt();
} else {
try {
channel.close();
} catch (final IOException ioe) {
System.out.println(ioe.getMessage());
}
}
}
}
};
interruptor.setDaemon(true);
interruptor.start();
final ByteBuffer buffer = ByteBuffer.allocate(32768);
int i = 0;
try {
while (true) {
buffer.clear();
buffer.put(newBuffer(buffer.capacity()));
buffer.flip();
channel.write(buffer);
System.out.print('X');
if (++i % 80 == 0) {
System.out.println();
Thread.sleep(100);
}
}
} catch (final ClosedByInterruptException cbie) {
System.out.println("Closed via Thread.interrupt()");
} catch (final AsynchronousCloseException ace) {
System.out.println("Closed via Channel.close()");
}
}
}在上面的例子中,我正在写入一个SocketChannel,但是没有人从另一边读取,所以写操作最终会挂起。
这个示例在JDK-1.6运行时工作得很好,输出如下:
Press Enter to interrupt I/O
XXXX
Interrupting...
Closed via Thread.interrupt()-意味着只有128 k的数据被写入TCP套接字的缓冲区。但是,当由JDK-1.7 (1.7.0_25-b15和1.7.0-u40-b37)运行时,相同的代码会出现在IOException中。
Press Enter to interrupt I/O
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
XXXXXXXXXXX
Exception in thread "main" java.io.IOException: Broken pipe
at sun.nio.ch.FileDispatcherImpl.write0(Native Method)
at sun.nio.ch.SocketDispatcher.write(SocketDispatcher.java:47)
at sun.nio.ch.IOUtil.writeFromNativeBuffer(IOUtil.java:93)
at sun.nio.ch.IOUtil.write(IOUtil.java:65)
at sun.nio.ch.SocketChannelImpl.write(SocketChannelImpl.java:487)
at com.example.TestBlockingNio.main(TestBlockingNio.java:109)有人能解释一下这种不同的行为吗?
发布于 2013-10-22 11:55:21
显然,在特定JVM版本如何将服务器套接字绑定到端口方面存在差异。
结果发现,我的第三方进程监听了127.0.0.1:10000,这在SocketChannel.open(new InetSocketAddress(10000))期间从未导致SocketChannel.open(new InetSocketAddress(10000))。
同时,1.6VM正在使用en0成功地连接到自身,而1.7-VM则使用lo0连接到外部进程。一旦进程被终止,JVM行为在不同版本之间就会再次保持一致。
https://stackoverflow.com/questions/19499160
复制相似问题