1. ホーム
  2. java

[解決済み] ノンブロッキングIOと非同期IOの比較とJavaでの実装

2023-06-10 23:42:01

質問

これらの2つの概念の違いを自分自身で要約しようとしています(人々が1つの文でこれらの両方を使用しているのを見ると本当に混乱するので、"非同期 IO" のように、それが何を意味するのかを理解しようとしています)。

私の理解では、ノンブロッキング IO は、データが準備できれば IO を処理し、そうでなければエラーを返すか何もしないかという OS の主要なメカニズムです。

非同期IOでは、コールバックを提供するだけで、データが利用可能になったときにアプリケーションに通知されます。

では、実際にquot;non-blocking async IO"とは何なのでしょうか?そして、どのようにJavaで実装することができるのでしょうか(標準のJDKで、外部ライブラリなしで。 java.nio.channels.{Channels, Selector, SelectorKey}java.nio.channels.{AsynchronousSocketChannel} ): ノンブロッキングIO、非同期IO、ノンブロッキング非同期IO(もしそんなものがあれば)?

どのように解決するのですか?

<ブロッククオート

では、実際にquot;non-blocking async IO"とは何でしょうか?

これに答えるには、まず、以下のようなものは存在しないことを理解する必要があります。 非同期 I/O のブロック化 . 非同期の概念そのものが、待機やブロッキング、遅延がないことを指示しています。あなたが ノンブロッキング非同期 I/O ノンブロッキング のビットをさらに修飾するだけです。 非同期 という形容詞を修飾しているに過ぎません。つまり、効果的に ノンブロッキング非同期 I/O は少し冗長かもしれません。

I/Oは主に2種類あります。 同期(Synchronous 非同期 . 同期では、処理が完了するまで現在の実行スレッドをブロックする 一方 非同期は実行中のスレッドをブロックせず、OS カーネルに制御を渡して処理を進めます。カーネルは提出されたタスクが完了すると非同期スレッドに通知します。


非同期チャネルグループ

javaの非同期チャネルのコンセプトは、非同期チャネルグループによって支えられています。非同期チャネルグループは基本的に再利用のためにいくつかのチャネルをプールしています。非同期APIの消費者はグループからチャネルを取得し(JVMはデフォルトでチャネルを作成します)、チャネルは読み取り/書き込み操作を完了した後、自動的にそれ自体をグループに戻します。最終的に、非同期チャネルグループは 驚き , スレッドプールです。また、非同期チャネルはスレッドセーフです。

非同期チャネルグループをバックアップするスレッドプールのサイズは、次のJVMプロパティによって構成されます。

java.nio.channels.DefaultThreadPool.initialSize

これは、整数値が与えられると、そのサイズのスレッドプールを設定し、チャネルグループをバックアップします。チャネルグループは、開発者に対しては透過的に作成・維持されます。


そして、そのすべてがJavaでどのように実装できるのか

なるほど、よくぞ聞いてくれました。以下は AsynchronousSocketChannel (ノンブロッキングクライアントを開くために使用される Socket をリッスン中のサーバに送るために使用されます)。このサンプルは アプレスプロJava NIO.2 から抜粋し、私がコメントしたものです。

//Create an Asynchronous channel. No connection has actually been established yet
AsynchronousSocketChannel asynchronousSocketChannel = AsynchronousSocketChannel.open(); 

/**Connect to an actual server on the given port and address. 
   The operation returns a type of Future, the basis of the all 
   asynchronous operations in java. In this case, a Void is 
   returned because nothing is returned after a successful socket connection
  */
Void connect = asynchronousSocketChannel.connect(new InetSocketAddress("127.0.0.1", 5000)).get();


//Allocate data structures to use to communicate over the wire
ByteBuffer helloBuffer = ByteBuffer.wrap("Hello !".getBytes()); 

//Send the message

Future<Integer> successfullyWritten=  asynchronousSocketChannel.write(helloBuffer);

//Do some stuff here. The point here is that asynchronousSocketChannel.write() 
//returns almost immediately, not waiting to actually finish writing 
//the hello to the channel before returning control to the currently executing thread

doSomethingElse();

//now you can come back and check if it was all written (or not)

System.out.println("Bytes written "+successfullyWritten.get());

EDIT: 非同期NIOのサポートはJDK 1.7で行われたことを述べておく。