NIO的那些事儿

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

你可能感兴趣的:(职场,nio,休闲)