• 首页 首页 icon
  • 工具库 工具库 icon
    • IP查询 IP查询 icon
  • 内容库 内容库 icon
    • 快讯库 快讯库 icon
    • 精品库 精品库 icon
    • 问答库 问答库 icon
  • 更多 更多 icon
    • 服务条款 服务条款 icon

Java的OIO和NIO含代码

武飞扬头像
枫飞雪飘
帮助1

简介及示例

Java NIO(New I/O)和OIO(Old I/O)是Java提供的两种不同的I/O模型。

OIO(Old I/O)是传统的阻塞I/O模型,也称为同步I/O。在OIO模型中,每个I/O操作(如读写操作)都会阻塞当前线程,直到操作完成或发生错误。当一个线程在执行一个I/O操作时,它无法进行其他任务,必须等待I/O操作完成后才能继续执行。这导致需要为每个连接创建一个独立的线程来处理I/O操作,当连接数量较多时,线程开销会很大。

相比之下,NIO(New I/O)是一种非阻塞I/O模型,也称为异步I/O。NIO模型中引入了选择器(Selector)和通道(Channel)的概念。通过Selector,一个线程可以同时监视多个通道的事件,并在事件发生时进行处理,从而实现了单线程处理多个通道的能力。NIO提供了一系列的Buffer,使得数据读写更加灵活。在NIO模型中,可以使用单个线程处理多个连接,大大减少了线程开销。

下面是一个简单的Java OIO(阻塞I/O)的代码示例:

  1.  
    import java.io.BufferedReader;
  2.  
    import java.io.IOException;
  3.  
    import java.io.InputStreamReader;
  4.  
    import java.io.PrintWriter;
  5.  
    import java.net.ServerSocket;
  6.  
    import java.net.Socket;
  7.  
     
  8.  
    public class OIOExample {
  9.  
    public static void main(String[] args) throws IOException {
  10.  
    ServerSocket serverSocket = new ServerSocket(8080);
  11.  
     
  12.  
    while (true) {
  13.  
    Socket clientSocket = serverSocket.accept();
  14.  
     
  15.  
    BufferedReader in = new BufferedReader(new InputStreamReader(clientSocket.getInputStream()));
  16.  
    PrintWriter out = new PrintWriter(clientSocket.getOutputStream(), true);
  17.  
     
  18.  
    String message = in.readLine();
  19.  
    System.out.println("Received message: " message);
  20.  
     
  21.  
    out.println("Hello, Client!");
  22.  
     
  23.  
    in.close();
  24.  
    out.close();
  25.  
    clientSocket.close();
  26.  
    }
  27.  
    }
  28.  
    }
学新通

以上示例中,创建了一个ServerSocket并绑定到8080端口。通过accept()方法阻塞等待客户端连接,一旦有客户端连接进来,会创建一个新的Socket,并通过该Socket获取输入流和输出流。然后通过阻塞的方式进行读取和写入数据。

需要注意的是,在OIO模型中,每个连接都需要一个独立的线程来处理,当有大量的并发连接时,线程的创建和切换会带来较大的开销。

相比之下,NIO模型通过单线程处理多个通道的方式,减少了线程创建和切换的开销,提高了系统的并发能力。

下面是一个简单的Java NIO(非阻塞I/O)的代码示例:

  1.  
    import java.io.IOException;
  2.  
    import java.net.InetSocketAddress;
  3.  
    import java.nio.ByteBuffer;
  4.  
    import java.nio.channels.SelectionKey;
  5.  
    import java.nio.channels.Selector;
  6.  
    import java.nio.channels.ServerSocketChannel;
  7.  
    import java.nio.channels.SocketChannel;
  8.  
    import java.util.Iterator;
  9.  
    import java.util.Set;
  10.  
     
  11.  
    public class NIOExample {
  12.  
    public static void main(String[] args) throws IOException {
  13.  
    Selector selector = Selector.open();
  14.  
     
  15.  
    ServerSocketChannel serverChannel = ServerSocketChannel.open();
  16.  
    serverChannel.socket().bind(new InetSocketAddress(8080));
  17.  
    serverChannel.configureBlocking(false);
  18.  
    serverChannel.register(selector, SelectionKey.OP_ACCEPT);
  19.  
     
  20.  
    while (true) {
  21.  
    int readyChannels = selector.select();
  22.  
     
  23.  
    if (readyChannels == 0) {
  24.  
    continue;
  25.  
    }
  26.  
     
  27.  
    Set<SelectionKey> selectedKeys = selector.selectedKeys();
  28.  
    Iterator<SelectionKey> keyIterator = selectedKeys.iterator();
  29.  
     
  30.  
    while (keyIterator.hasNext()) {
  31.  
    SelectionKey key = keyIterator.next();
  32.  
     
  33.  
    if (key.isAcceptable()) {
  34.  
    ServerSocketChannel server = (ServerSocketChannel) key.channel();
  35.  
    SocketChannel client = server.accept();
  36.  
    client.configureBlocking(false);
  37.  
    client.register(selector, SelectionKey.OP_READ);
  38.  
    } else if (key.isReadable()) {
  39.  
    SocketChannel client = (SocketChannel) key.channel();
  40.  
    ByteBuffer buffer = ByteBuffer.allocate(1024);
  41.  
    int bytesRead = client.read(buffer);
  42.  
     
  43.  
    if (bytesRead > 0) {
  44.  
    buffer.flip();
  45.  
    byte[] data = new byte[bytesRead];
  46.  
    buffer.get(data);
  47.  
    String message = new String(data);
  48.  
    System.out.println("Received message: " message);
  49.  
    } else if (bytesRead < 0) {
  50.  
    client.close();
  51.  
    }
  52.  
    }
  53.  
     
  54.  
    keyIterator.remove();
  55.  
    }
  56.  
    }
  57.  
    }
  58.  
    }
学新通

以上示例中,通过Selector来处理多个通道的读取事件。当有新的连接进来时,会将客户端SocketChannel注册到Selector上,监听读取事件(OP_READ),然后在循环中通过遍历selectedKeys来处理各个事件。

总结

区别:

  • 阻塞 vs 非阻塞:OIO是阻塞I/O模型,每个I/O操作都是阻塞的,即线程在执行I/O操作时会一直等待直到操作完成。NIO是非阻塞I/O模型,它使用Selector来实现非阻塞操作,允许单个线程处理多个通道的I/O事件。
  • 多线程 vs 单线程:OIO模型中,每个连接都需要创建一个独立的线程进行处理,当连接数量较多时,线程开销较大。NIO模型中,可以使用单个线程处理多个连接,减少了线程开销。
  • 通道和缓冲区:NIO引入了Channel和Buffer的概念,Channel用于读写数据,Buffer用于数据的存储和传输。OIO使用InputStream和OutputStream来进行数据的读写。

联系:

  • 都属于Java的I/O模型:无论是NIO还是OIO,都是Java提供的用于进行输入输出操作的模型。
  • 都可以实现网络编程:无论是NIO还是OIO,都可以用于实现网络编程,例如处理Socket连接、读写数据等。

总结来说,Java NIO相比于OIO提供了更高性能、更灵活的I/O操作方式,特别适用于处理大量连接的高并发场景。使用NIO可以充分利用单线程处理多个连接,减少线程开销。但是NIO的编程模型相对复杂,相比于OIO需要更多的代码和理解。选择使用哪种模型取决于具体的应用需求和场景。

如何选择

选择使用Java OIO(旧的I/O)还是Java NIO(新的I/O)取决于应用的需求和场景。以下是一些指导原则来帮助选择适合的I/O模型:

使用Java OIO(阻塞I/O)的情况:

  1. 简单性要求:如果你的应用相对简单,只需要处理少量的连接和数据,且对性能要求不高,使用OIO可以更容易编写和理解代码。
  2. 传统的阻塞模型:如果你习惯了传统的阻塞I/O编程模型,且代码已经使用了OIO,没有特别的性能需求,那么可以继续使用OIO。

使用Java NIO(非阻塞I/O)的情况:

  1. 高并发和大规模连接:如果你的应用需要处理大量的并发连接,例如高性能的服务器应用、网络游戏等,使用NIO可以更好地处理并发连接和提高吞吐量。
  2. 非阻塞操作:如果你需要在一个线程中处理多个通道的I/O操作,例如事件驱动编程、实现高性能的代理服务器等,使用NIO的Selector机制可以避免线程开销,提高效率。
  3. I/O操作与其他任务并发:如果你的应用需要将I/O操作与其他任务并发处理,例如同时处理网络I/O和计算任务,使用NIO可以更好地实现并发和资源的充分利用。

需要注意的是,NIO的编程模型相对复杂,相比于OIO需要更多的代码和理解。在使用NIO时,需要仔细考虑事件的处理逻辑和线程安全性。此外,NIO在某些场景下可能不如OIO稳定,例如处理低延迟和实时性要求较高的应用。

这篇好文章是转载于:学新通技术网

  • 版权申明: 本站部分内容来自互联网,仅供学习及演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,请提供相关证据及您的身份证明,我们将在收到邮件后48小时内删除。
  • 本站站名: 学新通技术网
  • 本文地址: /boutique/detail/tanhgjecaf
系列文章
更多 icon
同类精品
更多 icon
继续加载