NIO学习笔试(5)-提高篇

nio最大的特点在于不阻塞,但是如果要写入一个很大的文件,缓冲区满了,所以,程序还是会阻塞。解决的办法是一次只写一小块,这么做的话,就要把每次写的进度保存下来。我们可以利用SelectionKey.attach()方法,把一个selectionKey和一个对象“绑定”起来。

下面写一个小小的DEMO,服务器发送三个字符符给客户机,香港空间,每次发送一个。

对于读大文件,也可以作类似的处理。

到目前为止,我们都只有利用一个线程来处理所有请求,显然,这样会浪费多核CPU的优势。所以,我们要利用起多线程来。我想到的一种多线程的方式是多线程select(),因为一个channel可以注册到多个Selector上,把ServerSocketChannel注册到多个线程上的Selector上,让多线程竞争accept。另一种多线程的方式:把I/0操作及其它占用时间的操作丢给线程池去完成。还有一种方式,主线程的Selector负责accept,这样可以保证所有连接都被响应,工作线程的Selector去处理读/写请求。不管怎么样,总是不要让多线程去处理同一个SelectionKey(尽管它是线程安全的),因为readyOps( )方法返回的就绪状态指示只是一个提示,不是保证。底层的通道在任何时候都会不断改变。其他线程可能在通道上执行操作并影响它的就绪状态。即使使用线程池的方式,在对一个OP进程响应的时候,反注册掉这个OP,线程工作完后,再注册上这个OP,防止在这个线程工作时,其它线程也操作同一个channel。

另外,当一个请求完成后怎么办?SelectionKey和attach的对象不会自动回收。我的意见是,给每个selectionKey attach一个对象,来记录它们的活动情况,遍历selector.keys(),关闭长时间没活动的channel,相当于keepAlive机制。

一个SelectionKey对应一个Selector上的Channel,通过channel.keyFor(selector)取出相应的SelectionKey。也就是说,香港空间,一个channel在一个Selector上,读/写都是一个SelectionKey。所以SelectionKey的cancel方法会把整个channel也取消掉,而不是只取消读或写。

,香港服务器顺境的美德是节制,逆境的美德是坚韧,这后一种是较为伟大的德性。

NIO学习笔试(5)-提高篇

相关文章:

你感兴趣的文章:

标签云: