Java的OIO和NIO含代码
简介及示例
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)的代码示例:
-
import java.io.BufferedReader;
-
import java.io.IOException;
-
import java.io.InputStreamReader;
-
import java.io.PrintWriter;
-
import java.net.ServerSocket;
-
import java.net.Socket;
-
-
public class OIOExample {
-
public static void main(String[] args) throws IOException {
-
ServerSocket serverSocket = new ServerSocket(8080);
-
-
while (true) {
-
Socket clientSocket = serverSocket.accept();
-
-
BufferedReader in = new BufferedReader(new InputStreamReader(clientSocket.getInputStream()));
-
PrintWriter out = new PrintWriter(clientSocket.getOutputStream(), true);
-
-
String message = in.readLine();
-
System.out.println("Received message: " message);
-
-
out.println("Hello, Client!");
-
-
in.close();
-
out.close();
-
clientSocket.close();
-
}
-
}
-
}
以上示例中,创建了一个ServerSocket并绑定到8080端口。通过accept()
方法阻塞等待客户端连接,一旦有客户端连接进来,会创建一个新的Socket,并通过该Socket获取输入流和输出流。然后通过阻塞的方式进行读取和写入数据。
需要注意的是,在OIO模型中,每个连接都需要一个独立的线程来处理,当有大量的并发连接时,线程的创建和切换会带来较大的开销。
相比之下,NIO模型通过单线程处理多个通道的方式,减少了线程创建和切换的开销,提高了系统的并发能力。
下面是一个简单的Java NIO(非阻塞I/O)的代码示例:
-
import java.io.IOException;
-
import java.net.InetSocketAddress;
-
import java.nio.ByteBuffer;
-
import java.nio.channels.SelectionKey;
-
import java.nio.channels.Selector;
-
import java.nio.channels.ServerSocketChannel;
-
import java.nio.channels.SocketChannel;
-
import java.util.Iterator;
-
import java.util.Set;
-
-
public class NIOExample {
-
public static void main(String[] args) throws IOException {
-
Selector selector = Selector.open();
-
-
ServerSocketChannel serverChannel = ServerSocketChannel.open();
-
serverChannel.socket().bind(new InetSocketAddress(8080));
-
serverChannel.configureBlocking(false);
-
serverChannel.register(selector, SelectionKey.OP_ACCEPT);
-
-
while (true) {
-
int readyChannels = selector.select();
-
-
if (readyChannels == 0) {
-
continue;
-
}
-
-
Set<SelectionKey> selectedKeys = selector.selectedKeys();
-
Iterator<SelectionKey> keyIterator = selectedKeys.iterator();
-
-
while (keyIterator.hasNext()) {
-
SelectionKey key = keyIterator.next();
-
-
if (key.isAcceptable()) {
-
ServerSocketChannel server = (ServerSocketChannel) key.channel();
-
SocketChannel client = server.accept();
-
client.configureBlocking(false);
-
client.register(selector, SelectionKey.OP_READ);
-
} else if (key.isReadable()) {
-
SocketChannel client = (SocketChannel) key.channel();
-
ByteBuffer buffer = ByteBuffer.allocate(1024);
-
int bytesRead = client.read(buffer);
-
-
if (bytesRead > 0) {
-
buffer.flip();
-
byte[] data = new byte[bytesRead];
-
buffer.get(data);
-
String message = new String(data);
-
System.out.println("Received message: " message);
-
} else if (bytesRead < 0) {
-
client.close();
-
}
-
}
-
-
keyIterator.remove();
-
}
-
}
-
}
-
}
以上示例中,通过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)的情况:
- 简单性要求:如果你的应用相对简单,只需要处理少量的连接和数据,且对性能要求不高,使用OIO可以更容易编写和理解代码。
- 传统的阻塞模型:如果你习惯了传统的阻塞I/O编程模型,且代码已经使用了OIO,没有特别的性能需求,那么可以继续使用OIO。
使用Java NIO(非阻塞I/O)的情况:
- 高并发和大规模连接:如果你的应用需要处理大量的并发连接,例如高性能的服务器应用、网络游戏等,使用NIO可以更好地处理并发连接和提高吞吐量。
- 非阻塞操作:如果你需要在一个线程中处理多个通道的I/O操作,例如事件驱动编程、实现高性能的代理服务器等,使用NIO的Selector机制可以避免线程开销,提高效率。
- I/O操作与其他任务并发:如果你的应用需要将I/O操作与其他任务并发处理,例如同时处理网络I/O和计算任务,使用NIO可以更好地实现并发和资源的充分利用。
需要注意的是,NIO的编程模型相对复杂,相比于OIO需要更多的代码和理解。在使用NIO时,需要仔细考虑事件的处理逻辑和线程安全性。此外,NIO在某些场景下可能不如OIO稳定,例如处理低延迟和实时性要求较高的应用。
这篇好文章是转载于:学新通技术网
- 版权申明: 本站部分内容来自互联网,仅供学习及演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,请提供相关证据及您的身份证明,我们将在收到邮件后48小时内删除。
- 本站站名: 学新通技术网
- 本文地址: /boutique/detail/tanhgjecaf
-
photoshop保存的图片太大微信发不了怎么办
PHP中文网 06-15 -
《学习通》视频自动暂停处理方法
HelloWorld317 07-05 -
word里面弄一个表格后上面的标题会跑到下面怎么办
PHP中文网 06-20 -
Android 11 保存文件到外部存储,并分享文件
Luke 10-12 -
photoshop扩展功能面板显示灰色怎么办
PHP中文网 06-14 -
微信公众号没有声音提示怎么办
PHP中文网 03-31 -
excel下划线不显示怎么办
PHP中文网 06-23 -
excel打印预览压线压字怎么办
PHP中文网 06-22 -
TikTok加速器哪个好免费的TK加速器推荐
TK小达人 10-01 -
怎样阻止微信小程序自动打开
PHP中文网 06-13