解决方案 »
- request.setAttribute()如何将xml文件设置进去
- 梅花日历控件在ASP.net中如何实现?
- jstl问题
- 是不是每次运行一个servlet都要修改web.xml文件
- abc\def".replaceAll("\","//")为何报异常?
- run ejb时的错误如下
- 在rmi-spec-1.3里看到有关RMI CALL是如何利用HTTP协议穿透firewalls的内容,其中有不明白的地方
- EJB2.0问题,请帮忙
- J2EE听着很熟,怎么才能下载到J2EE呢?
- JAVA 定时任务报错,求解
- java新人,请帮我解释下如下的代码程序
- 读取文件时报[java.net.SocketException: Connection reset]
只要socket空闲就会触发这个事件,网上了解到基本95%以上时间都会触发这个事件。
所以网上都是推荐有数据写入时才临时注册这个事件,发送数据后再取消这个事件。
引用火龙果的话:“有一些 NIO 框架就很少注册 OP_WRITE 事件的,直接写入,如果不适合时就会产生阻塞直到能写为止。
OP_WRITE 比 OP_READ 等事件处理麻烦很多,一不小心就会对性能产生严重的影响。 ”
关于OP_WRITE事件进一步了解
不对OP_WRITE进行处理的样例:
while (bb.hasRemaining()) {
socketChannel.write(bb);
}
这样写在大多数的情况下都没有什么问题。但是在客户端的网络环境很糟糕的情况下,服务器会遭到很沉重的打击。
因为如果客户端的网络或者是中间交换机的问题,使得网络传输的效率很低,这时候会出现服务器已经准备好的返回结果无法通过TCP/IP层传输到客户端。这时候在执行上面这段程序的时候就会出现以下情况:
(1) bb.hasRemaining()一直为“true”,因为服务器的返回结果已经准备好了。
(2) socketChannel.write(bb)的结果一直为0,因为由于网络原因数据一直传不过去。
(3) 因为是异步非阻塞的方式,socketChannel.write(bb)不会被阻塞,立刻被返回。
(4) 在一段时间内,这段代码会被无休止地快速执行着,消耗着大量的CPU的资源。事实上什么具体的任务也没有做,一直到网络允许当前的数据传送出去为止。
private void writeable(SelectionKey key) throws IOException {
SocketChannel socketChannel = (SocketChannel) key.channel();
BufferManager manager = (BufferManager) key.attachment(); int len = manager.outputWriteBuffer(socketChannel);
if (len == EOF_FLAG) {
throw new ConnectException("close channel.");
} if (manager.isCompleteWrite()) { // 代码1
manager.rest();
synchronized (ioSelectorsSyns.get(key.selector())) {
key.selector().wakeup();
key.interestOps(SelectionKey.OP_READ);
}
}
}
这里每次都会去检测缓冲是否已经写完,写完后立即取消掉这个管道的写事件,没有就继续等下次可写时再写。决不能阻塞掉NIO的选择器线程。