我们都知道,在当前的大数据时代背景下,I/O的速度比内存要慢,尤其是性能问题与I/O相关的问题更加突出。
目前成都创新互联已为近1000家的企业提供了网站建设、域名、网页空间、网站改版维护、企业网站设计、龙亭网站维护等服务,公司将坚持客户导向、应用为本的策略,正道将秉承"和谐、参与、激情"的文化,与客户和合作伙伴齐心协力一起成长,共同发展。
在许多应用场景中,I/O读写操作已经成为系统性能的一个重要瓶颈,这是不能忽视的。
I/O作为机器获取和交换信息的主要渠道,流是执行I/O操作的主要方法。
在计算机中,流表示信息的传输。流保持顺序,因此针对特定的机器或应用程序,我们通常将从外部获得的信息称为输入流(InputStream),将从机器或应用程序发送出去的信息称为输出流(OutputStream)。
它们一起被称为输入/输出流(I/O流)。
当机器或程序交换信息或数据时,它们通常首先将对象或数据转换为一种特定形式的流。
然后,通过流的传输,数据到达指定的机器或程序。在目标位置,流被转换回对象数据。
因此,流可以被视为一种携带数据的手段,促进数据的交换和传输。
Java的I/O操作类位于java.io包中。其中,InputStream、OutputStream、Reader和Writer类是I/O包中的四个基本类。
它们分别处理字节流和字符流。下面的图表说明了这一点:
+-------------+
| InputStream |
+------+------+
^
|
+---------+---------+
| FileInputStream |
+-----------------------+
+-------------+
| OutputStream |
+------+------+
^
|
+---------+---------+
| FileOutputStream |
+-----------------------+
+-------------+
| Reader |
+------+------+
^
|
+----------+---------+
| FileReader |
+-----------------------+
+-------------+
| Writer |
+------+------+
^
|
+----------+---------+
| FileWriter |
+-----------------------+
无论是文件读写还是网络传输/接收,信息的最小存储单元始终是字节。那么为什么I/O流操作被分类为字节流操作和字符流操作呢?
我们知道,将字符转换为字节需要编码,而这个过程可能是耗时的。
如果我们不知道编码类型,很容易遇到字符乱码等问题。因此,I/O流提供了与字符直接工作的接口,使我们在日常工作中可以方便地进行字符流操作。
InputStream和OutputStream是字节流的抽象类,这两个抽象类派生出了几个子类,每个子类都设计用于不同类型的操作。
根据具体要求,您可以选择不同的子类来实现相应的功能。
Reader和Writer是字符流的抽象类,这两个抽象类也派生出了几个子类,每个子类都设计用于不同类型的操作。具体细节如下图所示:
+---------+
| Reader |
+------+------+
^
|
+---------+---------+
| InputStreamReader |
+-----------------------+
| FileReader |
+-----------------------+
| CharArrayReader |
+-----------------------+
+---------+
| Writer |
+------+------+
^
|
+---------+---------+
| OutputStreamWriter |
+-----------------------+
| FileWriter |
+-----------------------+
| CharArrayWriter |
+-----------------------+
我们知道,I/O操作可以分为磁盘I/O操作和网络I/O操作。
前者涉及将数据从磁盘源读取到内存中,然后将读取的信息持久化到物理磁盘中。
后者涉及将网络中的信息获取到内存中,最终将信息传输回网络。
然而,无论是磁盘I/O还是网络I/O,在传统I/O系统中都会遇到显着的性能问题。
在传统I/O中,我们可以使用InputStream从源读取数据,并将数据流输入到缓冲区中。然后,我们可以使用OutputStream将数据输出到外部设备,包括磁盘和网络。
在继续之前,您可以查看操作系统中输入操作的具体过程,如下图所示:
的内核将数据复制到用户空间缓冲区中,然后read()系统调用返回。
在此过程中,数据首先从外部设备复制到内核空间,然后从内核空间复制到用户空间。
这导致了两次内存复制操作。这些操作导致不必要的数据复制和上下文切换,最终降低了I/O的性能。
在传统I/O中,InputStream的read()操作通常是使用while循环实现的。它持续等待数据准备好后才返回。
这意味着如果没有准备好的数据,读取操作将一直等待,导致用户线程被阻塞。
在连接请求较少的情况下,这种方法效果良好,提供快速的响应时间。
然而,在处理大量连接请求时,创建大量的监听线程变得必要。在这种情况下,如果线程等待未准备好的数据,它将被阻塞并进入等待状态。
一旦线程被阻塞,它们将不断争夺CPU资源,导致频繁的CPU上下文切换。这种情况增加了系统的性能开销。
这就是为什么在具有高并发需求的场景中,由于线程管理和上下文切换的高成本,传统的阻塞式I/O可能变得效率低下的原因。
通常使用异步编程和非阻塞I/O技术来缓解这些问题,并提高系统效率。
使用缓冲是优化读写流操作的有效方法,减少频繁的磁盘或网络访问,从而提高性能。以下是使用缓冲来优化读写流操作的一些方法:
以下是使用缓冲进行文件读写的示例代码片段:
try (BufferedReader reader = new BufferedReader(new FileReader("input.txt"));
BufferedWriter writer = new BufferedWriter(new FileWriter("output.txt"))) {
String line;
while ((line = reader.readLine()) != null) {
// 处理行
writer.write(line);
writer.newLine(); // 添加新行
}
} catch (IOException e) {
e.printStackTrace();
}
使用DirectBuffer是一种减少I/O操作中内存复制的技术,特别是在Java NIO(新I/O)的上下文中。
DirectBuffer允许您直接使用非堆内存,这可以导致Java和本地代码之间更有效的数据传输。
在涉及大量数据的I/O操作中,这可能特别有益。
以下是如何使用DirectBuffer减少内存复制的方法:
以下是在ByteBuffer中使用DirectBuffer以进行高效I/O的简化示例:
try (FileChannel channel = FileChannel.open(Paths.get("data.bin"), StandardOpenOption.READ)) {
int bufferSize = 4096; // 根据需要调整
ByteBuffer directBuffer = ByteBuffer.allocateDirect(bufferSize);
int bytesRead;
while ((bytesRead = channel.read(directBuffer)) != -1) {
directBuffer.flip(); // 准备读取
// 在直接缓冲区中处理数据
// ...
directBuffer.clear(); // 准备下一次读取
}
} catch (IOException e) {
e.printStackTrace();
}
避免阻塞并优化I/O操作是提高系统性能和响应性的关键。以下是实现这些目标的一些方法:
根据您的应用场景和要求,您可以实现其中一个或多个方法,以避免阻塞,优化I/O操作,并增强系统性能和响应性。
正如前面所讨论的,传统的I/O最初依赖于InputStream和OutputStream操作流,这些流按字节为单位工作。
在高并发和大数据的情况下,这种方法很容易导致阻塞,从而导致性能下降。
此外,从用户空间复制输出数据到内核空间,然后再复制到输出设备,增加了系统性能开销。
为了解决性能问题,传统的I/O后来引入了缓冲作为缓解阻塞的手段。
它使用缓冲块作为最小单元。然而,即使使用缓冲,整体性能仍然不够理想。
然后出现了NIO(新I/O),它基于缓冲块单元操作。
在缓冲的基础上,它引入了两个组件:“通道”和“选择器”。这些补充使得非阻塞I/O操作成为可能。
NIO非常适合具有大量I/O连接请求的情况。这三个组件共同增强了I/O的整体性能。
新闻标题:如何解决高并发中的I/O瓶颈?
URL分享:http://www.mswzjz.cn/qtweb/news12/220362.html
攀枝花网站建设、攀枝花网站运维推广公司-贝锐智能,是专注品牌与效果的网络营销公司;服务项目有等
声明:本网站发布的内容(图片、视频和文字)以用户投稿、用户转载内容为主,如果涉及侵权请尽快告知,我们将会在第一时间删除。文章观点不代表本网站立场,如需处理请联系客服。电话:028-86922220;邮箱:631063699@qq.com。内容未经允许不得转载,或转载时需注明来源: 贝锐智能