1. 只有非阻塞Channel才能注册,否则会报IllegalBlockingModeException。
2. sk.interestOps(sk.interestOps()& ~SelectionKey.OP_READ);
//处理业务
sk.interestOps(sk.interestOps()| SelectionKey.OP_READ);
sk.interestOps()操作必须在与register()操作在同一个线程,否则不起作用。这个观点被证明是错的。
package com.guojje.nio; import java.io.IOException; import java.net.InetSocketAddress; import java.nio.ByteBuffer; import java.nio.channels.ReadableByteChannel; import java.nio.channels.SelectionKey; import java.nio.channels.Selector; import java.nio.channels.ServerSocketChannel; import java.nio.channels.SocketChannel; import java.nio.channels.spi.SelectorProvider; import java.util.Iterator; import java.util.Set; public class NioServer { public static void main(String[] args) throws IOException, InterruptedException { ServerSocketChannel ssc = ServerSocketChannel.open(); ssc.bind(new InetSocketAddress("0.0.0.0", 8080)); // Thread.currentThread().sleep(100000); ssc.configureBlocking(false); Selector selector = SelectorProvider.provider().openSelector(); ssc.register(selector, SelectionKey.OP_ACCEPT); while (true) { int readyChannels = selector.select(); System.out.println("ready channels count:" + readyChannels); if (readyChannels > 0) { Set<SelectionKey> selectedKeys = selector.selectedKeys(); Iterator<SelectionKey> it = selectedKeys.iterator(); while(it.hasNext()){ SelectionKey sk = it.next(); it.remove(); if((sk.readyOps() & SelectionKey.OP_ACCEPT) != 0){ ServerSocketChannel serverChannel = (ServerSocketChannel)sk.channel(); SocketChannel sc = serverChannel.accept(); System.out.println(sc); sc.configureBlocking(false); sc.register(selector, SelectionKey.OP_READ); } if((sk.readyOps() & SelectionKey.OP_READ) != 0){ ReadableByteChannel rc = (ReadableByteChannel)sk.channel(); sk.interestOps(sk.interestOps() & ~SelectionKey.OP_READ); ByteBuffer bb = ByteBuffer.allocate(50); rc.read(bb); System.out.println(new String(bb.array(),0,bb.position())); //sk.interestOps(sk.interestOps() | SelectionKey.OP_READ); Thread anoThread = new Thread(new AnotherThread(sk)); anoThread.start(); anoThread.join(); } } } } } } package com.guojje.nio; import java.nio.channels.SelectionKey; public class AnotherThread implements Runnable { private SelectionKey sk; public AnotherThread(SelectionKey sk){ this.sk = sk; } @Override public void run() { sk.interestOps(sk.interestOps() | SelectionKey.OP_READ); } }
三、 一个数组byte[] bs = new byte[10],bs[0]=10, bs[1]=9, bs[2]=8
如果想把SocketChannel读入剩余7个元素,而不影响其他,可以这样:
ByteBuffer bb = ByteBuffer.wrap(bs,3,7).slice();
如果仅仅用ByteBuffer.wrap(bs,3,7),则bb的capacity仍为bs.length.
而用slice之后,bb的capacity为7,所以你对bb的任务操作都不会影响到前三个元素。
package com.guojje.nio; import java.nio.ByteBuffer; public class TestSlice { public static void main(String[] args) { byte[] bs = new byte[10]; bs[0]=10; bs[1]=9; bs[2]=8; ByteBuffer bb1 = ByteBuffer.wrap(bs,3,7); ByteBuffer bb2 = ByteBuffer.wrap(bs,3,7).slice(); System.out.println(bb1.capacity()); System.out.println(bb2.capacity()); } }
四、 ByteBuffer.put ()与 ByteBuffer.get()都会增长position,并且上限都是limit.
因为:
final int nextGetIndex() { // package-private if (position >= limit) throw new BufferUnderflowException(); return position++; }
final int nextPutIndex() { // package-private if (position >= limit) throw new BufferOverflowException(); return position++; }
position都会增长。
五、 一个 channal 对应同一个SelectionKey in the same selector
六、channel.register操作may block if invoked concurrently with another registration[another.register(...)]
or selection operation[selector.select(...)] involving in the same selector.
这是因为register操作需要regLock与keyLock锁。
七. selectionKey.cancel():
The key will be removed from all of the selector's key sets during the next selection operation[select(...)] 。
cancel may block briefly if invoked concurrently with a cancellation[cancel()] or selection operation[select(...)]
involving the same selector.
参考:http://www.blogjava.net/adapterofcoms/archive/2010/03/02/314242.html