ホームページ  >  記事  >  Java  >  Java 入出力 IO、NIO、AIO の比較分析

Java 入出力 IO、NIO、AIO の比較分析

王林
王林転載
2023-05-08 23:07:071543ブラウズ

    1. Java I/O 開発の歴史

    Java 入出力 IO、NIO、AIO の比較分析

    Java IO (入力/出力) は、 Java 言語 データの読み取りと書き込みのための API であり、さまざまな種類のデータの読み取りと書き込みのための一連のクラスとインターフェイスを提供します。以下は、Java IO の開発の歴史の簡単な紹介です。

    • JDK 1.0 (1996) オリジナルの Java IO は、バイト ストリーム (InputStream、OutputStream) と文字ストリーム (Reader、筆者)ブロッキングIO(BIO)モデルに基づく2種類。

    • JDK 1.1 (1997) JDK 1.1 は NIO (New IO) パッケージを導入し、バッファやチャネルなどの概念をサポートし、より効率的な IO を提供しました 動作モードはノンブロッキング IO を実現できます(NIO) モード。

    • JDK 1.4 (2002) JDK 1.4 では、バッファ付き Java NIO とも呼ばれる NIO.2 API が追加され、より強力なファイル処理機能とより効率的な IO 操作が提供されます。

    • JDK 7 (2011) JDK 7 では、NIO.2 の改良版が導入されています。NIO.2 は完了ポートを備え、AIO (非同期 IO) とも呼ばれ、非同期をサポートしています。IO メソッドは次のとおりです。多数の同時リクエストを処理する場合に利点があります。

    これら 3 つの違いは次のとおりです:

    Java 入出力 IO、NIO、AIO の比較分析

    • IO のブロック(BIO) BIO は Java のオリジナルの IO モデルであり、ブロッキング メソッドを使用してデータの読み取りおよび書き込み操作を実行します。つまり、スレッドが IO 操作を実行しているときに、読み取るデータがない場合、スレッドはブロックされ、読み取るデータが存在するかタイムアウトになるまで待機します。 BIO は、接続数が比較的少なく固定されているものの、同時実行機能が不十分なシナリオの処理に適しています。

    • ノンブロッキング IO (NIO) NIO は、Java 1.4 で導入された新しい IO モデルで、マルチプレクサ (セレクター) メカニズムを使用して、少数のチャンネルを同時に管理します。スレッドの数。これにより、単一のスレッドが複数のリクエストを同時に処理する効果が得られます。 NIO は高い同時実行性、高いスループット、および高い信頼性を備えており、接続数が多く接続時間が短いシナリオの処理に適しています。

    • 非同期 IO (AIO) AIO は、Java 1.7 でサポートされる IO モデルです。イベント駆動型のアプローチを使用してデータの読み取りと書き込みを行います。データの準備ができたら、次の方法で実行されます。コールバック関数を処理します。 NIO とは異なり、AIO の読み取りおよび書き込み操作は非同期であり、データの準備ができているかどうかを確認するためにポーリングする必要はありません。 AIO は、接続数が多く、接続時間が長く、読み取りおよび書き込み操作が多いシナリオの処理に適しています。

    2. Java IO

    2.1 はじめに

    Java プログラミングでは、IO (入力/出力) 操作は非常に一般的な操作であり、ファイルへの出力が含まれます。読み書き、ネットワーク通信など。 Java は、これらの操作をサポートするさまざまなクラスを提供します。この記事では、IO の基礎知識から始めて、徐々に深めて Java IO のあらゆる側面を紹介します。

    2.2 基本概念

    2.2.1 入力ストリームと出力ストリーム

    Java では、入力ストリーム (InputStream) と出力ストリーム (OutputStream) は 2 つの重要な抽象化の種類です。入力ストリームは、ファイル、ネットワーク接続、パイプなどの入力データのソースを表し、出力ストリームは、ファイル、ネットワーク接続、パイプなどの出力データの宛先を表します。入力ストリームと出力ストリームは、ストリーム オブジェクトを作成し、対応するメソッド インターフェイスを使用して読み取りおよび書き込み操作を実行することにより、同様の方法で使用されます。

    2.2.2 バイト ストリームと文字ストリーム

    Java の IO 操作は、バイト ストリームと文字ストリームの 2 つのタイプに分けることもできます。バイト ストリームはバイト (byte) 単位で動作し、画像や音声などのバイナリ データの処理に適しています。一方、文字ストリームは文字 (char) 単位で動作し、テキスト データの処理に適しています。テキストファイルなど。 Java では、バイト ストリームは主に、InputStream クラス、OutputStream クラスとそのサブクラスによって実装され、文字ストリームは主に Reader クラス、Writer クラスとそのサブクラスによって実装されます。

    2.2.3 バッファリングされたストリーム

    IO 操作を実行するとき、頻繁な読み取りおよび書き込み操作を実行する必要がある場合があり、頻繁な読み取りおよび書き込みによりパフォーマンスの問題が発生する可能性があります。この問題を解決するために、Java は IO 操作の効率を向上させるバッファー付きストリーム (Buffered Stream) を提供します。バッファリングされたストリームにより、内部キャッシュ領域を介した基礎となるリソースへのアクセス数が削減され、データの読み取りと書き込みの効率が向上します。

    2.3 Java IO の使用

    2.3.1 ファイルの読み取りと書き込み

    Java でのファイルの読み取りと書き込みは、開発において最も一般的な操作の 1 つです。以下は、ファイルの内容を読み取って出力する例です。

        try (FileInputStream fis = new FileInputStream("test.txt");
             InputStreamReader isr = new InputStreamReader(fis);
             BufferedReader br = new BufferedReader(isr)) {
            String line;
            while ((line = br.readLine()) != null) {
                System.out.println(line);
            }
        } catch (IOException e) {
            e.printStackTrace();
        }

    この例では、FileInputStream、InputStreamReader、BufferedReader などのクラスを使用してファイルの読み取りを完了します。まず、FileInputStream クラスを通じて入力ストリーム オブジェクトを作成し、読み取るファイルの名前を指定します。次に、InputStreamReader を使用してバイト ストリームを文字ストリームに変換し、次に BufferedReader を使用してテキスト コンテンツを 1 行ずつ読み取ります。

    同様に、Java でのファイルの作成も非常に簡単です。ファイルの作成例を次に示します:

    try (FileOutputStream fos = new FileOutputStream("test.txt");
         OutputStreamWriter osw = new OutputStreamWriter(fos);
         BufferedWriter bw = new BufferedWriter(osw)) {
        bw.write("Hello, world!");
    } catch (IOException e) {
        e.printStackTrace();
    }

    在这个示例中,我们使用了FileOutputStream、OutputStreamWriter和BufferedWriter等类来完成文件的写入。首先,我们通过FileOutputStream类创建了一个输出流对象,并指定了要写入的文件名称;然后通过OutputStreamWriter将字节流转换为字符流,再通过BufferedWriter实现按行写入文本内容。

    3、Java NIO

    3.1 简介

    Java NIO(New IO)是Java SE 1.4引入的一个新的IO API,它提供了比传统IO更高效、更灵活的IO操作。与传统IO相比,Java NIO的优势在于它支持非阻塞IO和选择器(Selector)等特性,能够更好地支持高并发、高吞吐量的应用场景。本文将从NIO的基础知识讲起,逐步深入,介绍Java NIO的各个方面。

    3.2 核心概念

    3.2.1 选择器(Selector)

    选择器是Java NIO中的一个重要组件,它可以用于同时监控多个通道的读写事件,并在有事件发生时立即做出响应。选择器可以实现单线程监听多个通道的效果,从而提高系统吞吐量和运行效率。

    3.2.2 通道(Channel)

    通道是一个用于读写数据的对象,类似于Java IO中的流(Stream)。与流不同的是,通道可以进行非阻塞式的读写操作,并且可以同时进行读写操作。通道分为两种类型:FileChannel和SocketChannel,分别用于文件和网络

    通信。

    3.2.3 缓冲区(Buffer)

    在Java NIO中,所有数据都是通过缓冲区对象进行传输的。缓冲区是一段连续的内存块,可以保存需要读写的数据。缓冲区对象包含了一些状态变量,例如容量(capacity)、限制(limit)、位置(position)等,用于控制数据的读写。

    3.3 Java NIO的使用

    3.3.1 缓冲区操作

    Java NIO中的缓冲区操作主要包括数据读取和数据写入两种操作。下面是一个简单的缓冲区读取示例:

    ByteBuffer buffer = ByteBuffer.allocate(1024);
    try (FileChannel channel = new FileInputStream("test.txt").getChannel()) {
        int bytesRead = channel.read(buffer);
        while (bytesRead != -1) {
            buffer.flip();
            while (buffer.hasRemaining()) {
                System.out.print((char) buffer.get());
            }
            buffer.clear();
            bytesRead = channel.read(buffer);
        }
    } catch (IOException e) {
        e.printStackTrace();
    }

    在这个示例中,我们使用了FileChannel类和ByteBuffer类来完成文件的读取。首先,我们通过FileInputStream类创建了一个输入流对象,然后通过getChannel()方法获取到对应的通道对象;接着,我们创建了一个容量为1024字节的ByteBuffer对象,并调用read()方法从通道中读取数据,将读取到的数据保存在缓冲区中。读取完成后,我们通过flip()方法将缓冲区切换为读模式,并使用hasRemaining()和get()方法逐个读取数据;最后通过clear()方法清空缓冲区,准备进行下一轮读取。

    Java NIO中的缓冲区写操作也非常类似,下面是一个简单的缓冲区写入示例:

    ByteBuffer buffer = ByteBuffer.wrap("Hello, world!".getBytes());
    try (FileChannel channel = new FileOutputStream("test.txt").getChannel()) {
        channel.write(buffer);
    } catch (IOException e) {
        e.printStackTrace();
    }

    在这个示例中,我们使用了FileChannel类和ByteBuffer类来完成文件的写入。首先,我们通过ByteBuffer.wrap()方法将字符串转换为ByteBuffer对象;然后,我们通过FileOutputStream类创建了一个输出流对象,再通过getChannel()方法获取到对应的通道对象;接着,我们调用write()方法将缓冲区中的数据写入通道中,完成文件写入操作。

    3.3.2 通道操作

    Java NIO中的通道(Channel)是用于进行数据传输的对象。通道可以连接到源或目标节点,用于读取和写入数据。与传统的Java IO不同,NIO中的通道可以实现非阻塞式地读写数据,从而提高了应用程序的性能和并发处理能力。

    要使用通道进行读写操作,首先需要打开通道。Java NIO中有多种类型的通道,每种通道都提供了自己的打开方式。例如,要打开一个文件通道,可以通过FileInputStream或FileOutputStream对象获取对应的FileChannel对象,如下所示:

        FileChannel channel = new FileInputStream("file.txt").getChannel();

    读取数据 一旦打开了通道,就可以开始读取数据。在NIO中,数据通过缓冲区进行传输。要读取数据,需要将数据存储在缓冲区中,然后从缓冲区中读取数据。以下是一个简单的读取操作示例:

    ByteBuffer buffer = ByteBuffer.allocate(1024);
    // 从通道中读取数据
    int bytesRead = channel.read(buffer);
    while (bytesRead != -1) {
        // 切换为读模式
        buffer.flip();
        // 读取缓冲区中的数据
        while (buffer.hasRemaining()) {
            System.out.print((char) buffer.get());
        }
        // 清空缓冲区
        buffer.clear();
        bytesRead = channel.read(buffer);
    }

    在这个示例中,我们首先创建了一个容量为1024字节的ByteBuffer对象,并使用channel.read()方法从文件通道中读取数据。读取到数据后,我们将ByteBuffer切换为读模式,再使用hasRemaining()和get()方法逐个读取缓冲区中的数据。

    写入数据 要写入数据,也需要将数据存储在缓冲区中,然后将缓冲区中的数据写入到通道中。以下是一个简单的写入操作示例:

    ByteBuffer buffer = ByteBuffer.wrap("Hello, world!".getBytes());
    // 将数据写入通道
    channel.write(buffer);

    在这个示例中,我们首先使用ByteBuffer.wrap()方法将字符串转换为ByteBuffer对象,在通过channel.write()方法将ByteBuffer中的数据写入到通道中。

    4、Java AIO

    Java AIO(Asynchronous IO)是一种基于事件和回调的IO模型,相比Java BIO(Blocking IO)和Java NIO(Non-blocking IO),它具有更高的并发性、更高的吞吐量和更高的可靠性。本文将介绍Java AIO的原理、特点和应用。

    4.1 Java AIO の原理

    Java AIO は、データの読み取りおよび書き込み操作に非同期 IO を使用します。Java NIO とは異なり、データの準備ができているかどうかを確認するためにポーリングする必要はありませんが、オペレーティング システムが終了します。データの準備ができると、オペレーティング システムはアプリケーションに通知し、コールバック関数で処理します。

    AIO は、AsynchronousChannel、CompletionHandler、
    AsynchronousServerSocketChannel の 3 つのコア コンポーネントを使用します。このうち、AsynchronousChannel はデータの読み取り/書き込み用のチャネル、CompletionHandler は I/O 操作完了時のコールバック メソッド、AsynchronousServerSocketChannel はクライアントの接続要求を監視するために使用される非同期サーバー側ソケット チャネルです。

    データの準備ができると、オペレーティング システムはアプリケーションに通知し、I/O 操作の完了時にコールバック関数内のコールバック メソッドを実行します。これにより、I/O 操作の完了を待ってスレッドがブロックされる状況が回避され、プログラムの効率と同時処理能力が向上します。

    4.2 Java AIO の特性

    • 高い同時実行性: Java AIO は、データの読み取りおよび書き込み操作に非同期 IO を使用し、高い同時実行処理能力を実現します。

    • 高スループット: Java AIO は、非同期の読み取りおよび書き込み操作をサポートし、複数のリクエストを同時に処理できるため、データの読み取りおよび書き込みの効率とスループットが向上します。

    • 高信頼性: Java AIO はデータの読み取りおよび書き込み操作に非同期 IO を使用するため、I/O 操作の完了を待つスレッドのブロックを回避でき、プログラムの信頼性が向上します。 。

    • シンプルで使いやすい: Java AIO はシンプルで使いやすい API を提供し、複雑なコードを記述せずに非同期 IO 操作を実装できます。

    4.3 Java AIO のアプリケーション

    Java AIO は、多数の同時接続を必要とするシナリオに適していますが、各接続ではメッセージなどのデータのやり取りがほとんどありません。ベースのアプリケーション プログラム、リモート プロシージャ コール (RPC) などこれらのアプリケーション シナリオでは、AIO によってプログラムのパフォーマンスと同時処理能力が大幅に向上し、高スループットと低遅延に対するユーザーの要件を満たすことができます。

    さらに、Java AIO は、チャット ルーム サーバー、オンライン ゲーム サーバーなどの高性能ネットワーク サーバーの開発にも使用できます。 AIO は入力ストリームと出力ストリームの非同期読み取りをサポートしているため、複数のクライアント要求を同時に処理でき、サーバーの同時処理能力が効果的に向上します。

    概要

    高性能、高同時 IO モデルとして、Java AIO には多くの利点がありますが、いくつかの欠点もあります。たとえば、負荷の小さい接続では、AIO のオーバーヘッドが発生する可能性があります。パフォーマンスの低下に。したがって、実際のアプリケーションでは、さまざまな要素を比較検討して評価し、実際のニーズに基づいて選択する必要があります。

    5. 関連する面接の質問

    1. Java IO と NIO とは何ですか?

    Java IO (入力/出力) は、データ送信にバイト ストリームと文字ストリームを使用する Java の従来の入出力操作です。
    Java NIO (新しい入力/出力) は、Java 1.4 で導入された新しい入出力 API であり、データをより効率的に処理します。

    2.ブロッキング IO とノンブロッキング IO とは何ですか?

    ブロッキング IO (ブロッキング IO) は、IO 操作中に IO が完了するまで待機し、その間は他の操作を実行できません。
    ノンブロッキング IO (ノンブロッキング IO) は、IO 操作を実行するときに永遠に待機せず、すぐに結果を返します。IO が完全に完了していない場合は、引き続き他の作業を行うことができます。

    3. バッファとは何ですか?バッファにはどのような種類がありますか?

    バッファはデータを格納するために使用される配列であり、IO 操作を実行するときは、データの読み取りと書き込みにバッファを使用する必要があります。
    Java のバッファは、バイト バッファ (ByteBuffer、CharBuffer、ShortBuffer など) とダイレクト バッファ (DirectByteBuffer、DirectCharBuffer、DirectShortBuffer など) に分かれています。

    4.チャンネルとは何ですか?

    チャネルは、NIO でのデータ送信に使用されるオブジェクトであり、データの読み取りおよび書き込みのために送信元ノードまたは宛先ノードに接続できます。

    5.セレクターとは何ですか?

    セレクターは、NIO のオブジェクトです。セレクターに登録されているチャネルをポーリングして、イベント (読み取り可能、書き込み可能など) があるかどうかを確認できるため、IO のブロックを回避できます。IO が完了するまで待つ必要があります。完了。

    6. Java IO と NIO の違いは何ですか?

    Java IO はストリームに基づいてデータを送信しますが、NIO はバッファとチャネルに基づいてデータを送信します。
    Java IO はブロッキングですが、NIO はブロッキング モードまたは非ブロッキング モードにできます。
    Java IO はより多くのスレッドを使用し、各 IO 操作にはスレッドの作成が必要ですが、NIO は単一のスレッドを使用して複数の IO 操作を処理できます。

    7. ファイルチャネルとは何ですか?

    ファイル チャネルは、ファイルの読み取りと書き込みに NIO で使用されるチャネルであり、ランダム アクセスやメモリ マップされたファイルなどの高度な機能をサポートします。

    8. Java IO と NIO はどちらが速いですか?

    大量の小さなデータの場合、Java IO はバッファを通じてすべてのデータを一度に読み取ることができるため、高速になる可能性があります。
    大きなデータ ブロックが多数ある場合、NIO はゼロコピー テクノロジを使用してデータをディスクからメモリに直接読み取り、データ コピーのオーバーヘッドを削減できるため、高速になる可能性があります。

    以上がJava 入出力 IO、NIO、AIO の比較分析の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

    声明:
    この記事はyisu.comで複製されています。侵害がある場合は、admin@php.cn までご連絡ください。