什么是NIO?什么是BIO?NIO 和 BIO 有什么区别?

一、什么是NIO1.概念NIO是JAVA1.4中引入的 , 被称为new I/O , 也有说是non-blocking I/O , NIO被成为同步非阻塞的IO 。
 
2.跟BIO流的区别

  1. BIO是面向流的 , NIO是面向块(缓冲区)的 。
  2. BIO的流都是同步阻塞的 , 而NIO是同步非阻塞的 。
  3. NIO会等待数据全部传输过来再让线程处理 , BIO是直接让线程等待 。
  4. NIO有选择器 , 而BIO没有 。
  5. NIO是采用管道和缓存区的形式来处理数据的 , 而BIO是采用输入输出流来处理的 。
  6. NIO是可以双向的 , BIO只能够单向 。
 
二、NIO常用组件Channel和Buffer的使用1.代码这里以文件复制为例
public class test {public static void main(String[] args){try{//存在的照片File inFile=new File("C:\Users\Administrator\Desktop\study.PNG");//复制后要存放照片的地址File outFile=new File("C:\Users\Administrator\Desktop\study1.PNG");//打开流FileInputStream fileInputStream=new FileInputStream(inFile);FileOutputStream fileOutputStream=new FileOutputStream(outFile);/*** RandomaccessFile accessFile=new RandomAccessFile(inFile,"wr");*FileChannel inFileChannel=accessFile.getChannel();*和下面两行代码是一样的 , 都是可以拿到FileChannel*///获取ChannelFileChannel inFileChannel=fileInputStream.getChannel();FileChannel outFileChannel=fileOutputStream.getChannel();//创建bufferByteBuffer buffer=ByteBuffer.allocate(1024*1024);//读取到buffer中while (inFileChannel.read(buffer)!=-1){//翻转一下 , 就可以读取到全部数据了buffer.flip();outFileChannel.write(buffer);//读取完后要clearbuffer.clear();}//关闭inFileChannel.close();outFileChannel.close();fileInputStream.close();fileOutputStream.close();}catch (Exception e){}}}复制代码我的桌面上的确多了一张一模一样的图片
2.解释使用NIO的话 , 需要注意几个步骤:
  1. 打开流
  2. 获取通道
  3. 创建Buffer
  4. 切换到读模式 buffer.flip()
  5. 切换到写模式 buffer.clear(); 其实这里也看不出来它是怎么使用缓冲区的 , 上面这段代码中的while循环的作用和下面的代码是一样的
while ((i=fileInputStream.read())!=-1){fileOutputStream.write(i);}【什么是NIO?什么是BIO?NIO 和 BIO 有什么区别?】让我们赶紧开始NIO的编程
三、BIO和NIO的区别学习了Channel和Buffer的使用 , 我们就可以正式进入NIO的开发了
代码NIONIO服务端:只是接受客户端发送过来的数据 , 然后打印在控制台
/** * NIO * @author xuxiaobai */public class NIOTest {private final static int port = 8080;public static void main(String[] args) throws IOException {//启动服务端TCPServer();}/*** TCP服务端* 接受TCP** @throws IOException*/public static void TCPServer() throws IOException {//创建服务端多路复用选择器Selector selector = Selector.open();//创建服务端SocketChannelServerSocketChannel serverSocketChannel = ServerSocketChannel.open();//定义地址InetSocketAddress inetSocketAddress = new InetSocketAddress(InetAddress.getLocalHost(), port);//绑定地址serverSocketChannel.bind(inetSocketAddress);System.out.println("绑定成功:" + inetSocketAddress);//设置为非阻塞serverSocketChannel.configureBlocking(false);//注册服务端选择端 , 只接受accept事件serverSocketChannel.register(selector, SelectionKey.OP_ACCEPT);while (true) {//加上延时 , 什么原理我忘记了 , 只知道是为了防止死锁selector.select(500);//遍历服务端选择器的事件Iterator<SelectionKey> iterator = selector.selectedKeys().iterator();while (iterator.hasNext()) {SelectionKey next = iterator.next();if (!next.isValid()) {//该key无效直接跳过continue;}//注意if (next.isAcceptable()) {//1. accept事件//接收到accept事件 , 拿到channel , 这个是服务端SocketChannelServerSocketChannel channel = (ServerSocketChannel) next.channel();//accept得到连接客户端的channelSocketChannel accept = channel.accept();accept.configureBlocking(false);//注册write事件accept.register(selector, SelectionKey.OP_READ);iterator.remove();} else if (next.isReadable()) {//2. read事件//开启一个新的线程Thread thread = new Thread(() -> {SocketChannel channel = (SocketChannel) next.channel();ByteBuffer byteBuffer = ByteBuffer.allocate(1024);byteBuffer.clear();try {channel.read(byteBuffer);//开始处理数据byteBuffer.flip();byte[] bytes = new byte[byteBuffer.remaining()];byteBuffer.get(bytes);String x = new String(bytes);if(x.equals("")){//老是会莫名其妙地打印一些空行 , 打个补丁return;}System.out.println(x);if ("exit".equals(x)) {//关闭通道try {channel.close();} catch (IOException e) {e.printStackTrace();}next.cancel();}} catch (IOException e) {//出现异常的处理e.printStackTrace();try {channel.close();} catch (IOException ioe) {ioe.printStackTrace();}next.cancel();}});iterator.remove();thread.start();}}}}}


推荐阅读