java io 主要有3种:
jdk源码在 java.io 和 java.nio中
1. BIO (blocking io)
while(true){ Socket socket=null; socket=serverSocket.accept(); //主线程获取客户端连接 Thread workThread=new Thread(new Handler(socket)); //创建线程 workThread.start(); //启动线程 }
BIO的问题在于,如果是单线程,则无所谓性能问题,但是在高并发的情况下,如果要同时处理很多IO,每个线程都要阻塞等待IO准备好数据,
我们可以看到,accept方法是阻塞的,同时,accept后,也只是建立了socket链接,IO数据还没传输好,我们就已经分配线程run起来,阻塞等待数据了。
2. NIO (none blocking io) jdk4
Selector selector = Selector.open();
Set selectedKeys = selector.selectedKeys(); Iterator it = selectedKeys.iterator(); while (it.hasNext()) { SelectionKey key = (SelectionKey)it.next(); if ((key.readyOps() & SelectionKey.OP_ACCEPT) == SelectionKey.OP_ACCEPT) {
ServerSocketChannel ssc = (ServerSocketChannel)key.channel(); SocketChannel sc = ssc.accept();
sc.configureBlocking( false ); SelectionKey newKey = sc.register( selector, SelectionKey.OP_READ ); }else if ((key.readyOps() & SelectionKey.OP_READ) == SelectionKey.OP_READ) { Thread workThread=new Thread(new Handler(sc)); workThread.start(); it.remove(); } }
BIO 是事件注册的机制,不是在建立新的链接时就新建线程处理,而是在selector中注册事件,通过一个线程循环selector来监听事件发生。
这样我们可以注册数据ready事件,等到IO数据传输完毕,而不是socket建立时就开启线程阻塞等待。
3. AIO ( Asynchronous io, nio2 ) jdk7
// send message ByteBuffer message = ByteBuffer.wrap("Hello to all listeners".getBytes()); server.send(message, new InetSocketAddress(group, port)); // receive message final ByteBuffer buffer = ByteBuffer.allocate(100); client.receive(buffer, null, new CompletionHandler<SocketAddress, Object>() { @Override public void completed(SocketAddress address, Object attachment) { System.out.println("Message from " + address + ": " + new String(buffer.array())); } @Override public void failed(Throwable e, Object attachment) { System.err.println("Error receiving datagram"); e.printStackTrace(); } });
从例子我们可以清楚的看到,异步IO的特点是对于IO处理,采用了callback的异步调用方式,只要定义一个io数据准备完毕后的 completionHandler 的callback 函数, 到时候就会异步调用callback处理。