English | 简体中文 | 繁體中文 | Русский язык | Français | Español | Português | Deutsch | 日本語 | 한국어 | Italiano | بالعربية

Javaの基礎知識に関する雑記

1基本概念

IOはメインメモリと外部デバイス(ハードディスク、端末、ネットワークなど)間でデータをコピーするプロセスです。IOはオペレーティングシステムの基本的な機能実装であり、基本的にはI/Oコマンドを完了します。

すべての言語の実行時システムはIコマンドを実行することを提供しています。/Oのより高度なツール。(Cのprintfscanf、Javaのオブジェクト指向の封装)

2Java標準IOの振り返り

Java標準IOクラスライブラリはioがオブジェクト指向の抽象。

3.nio概要

nioはjavaNewIOの略称、在jdk1.4で提供される新しいAPI。Sunオフィシャルが宣伝する特性は以下の通りです:

–すべての原始タイプに対して(Buffer)キャッシュサポートを提供。

–文字コードエンコードデコード解決策。

–Channel:新しい原始I/O抽象。

–ロックとメモリマッピングファイルのファイルアクセスインターフェースをサポート。

–多路(non-bloking)非ブロッキング式の高可伸縮性ネットワークI/O。

本文はこれらの特性を中心に学習と紹介を行います。

4.Buffer&Chanel

ChannelとBufferはNIOの最も基本的なデータタイプ抽象。

Buffer:

–一連の連続したメモリブロック。

–NIOデータの読み書きの中間地。

Channel:

–データの源またはデータの目的地

–bufferにデータを提供したり、bufferデータを読み取るための、bufferオブジェクトの唯一のインターフェース。

–アシンクリーナイ/Oサポート

例子 1:CopyFile.java:

package sample;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.nio.ByteBuffer;
import java.nio.channels.FileChannel;
public class CopyFile {
	public static void main(String[] args) throws Exception {
		String infile = "C:\\copy.sql";
		String outfile = "C:\\copy.txt";
		// ソースファイルとターゲットファイルの入出渠道を取得 
		FileInputStream fin = new FileInputStream(infile);
		FileOutputStream fout = new FileOutputStream(outfile);
		// 入出渠道を取得 
		FileChannel fcin = fin.getChannel();
		FileChannel fcout = fout.getChannel();
		// バッファの作成 
		ByteBuffer buffer = ByteBuffer.allocate(1024);
		while (true) {
			// clearメソッドはバッファをリセットし、読み取りデータを受け入れる準備をします 
			buffer.clear();
			// 入力チャネルからデータをバッファに読み込みます 
			int r = fcin.read(buffer);
			// readメソッドは読み取ったバイト数を返します。これは0でもあり、チャネルがストリームの終わりに達している場合には返されます-1 
			if (r == -1) {
				break;
			}
			// flipメソッドにより、バッファが新しい読み取りデータを別のチャネルに書き込むことができます 
			buffer.flip();
			// 出力チャネルからデータをバッファに書き込みます 
			fcout.write(buffer);
		}
	}
}

その中で、bufferの内部構造は以下の通りです(以下の図は資料からコピーしました):

図2:bufferの内部構造

一つのbufferは、position、limit、capacityの3つの変数によって読み書きプロセスを制御されます。これらの変数の意味は以下のテーブルを参照してください:

パラメータ

書き込みモード    

読み取りモード

position

現在の書き込んだデータ単位数。

現在の読み取りのデータ単位位置。

limit

書き込める最大のデータ単位数を表し、容量と同じです。

読み取れる最大のデータ単位数を表し、先に書き込んだデータの単位データ量と一致します。

capacity

bufferの容量

bufferの容量

Bufferの一般的なメソッド:

flip(): 書き模式から読み取り模式に切り替えます

rewind(): positionを0にリセットし、一般的には再読み取りに使用されます。

clear(): bufferをクリアし、再び書き込む準備をします(positionは0に、limitはcapacityに設定されます)。

compact(): 未読データをbufferの先頭にコピーします。

mark()、reset(): markは位置をマークし、resetはその位置にリセットします。

Bufferの一般的なタイプ:ByteBuffer、MappedByteBuffer、CharBuffer、DoubleBuffer、FloatBuffer、IntBuffer、LongBuffer、ShortBuffer。

channelの一般的なタイプ: FileChannel、DatagramChannel(UDP)、SocketChannel(TCP)、ServerSocketChannel(TCP)

この機器上で簡単なパフォーマンステストを行いました。私のノートパソコンのパフォーマンスは一般的です。(詳細なコードは添付ファイルを参照してください。nio.sample.filecopyパッケージのサンプルを参照してください)以下は参考データです:

–场景1:拷贝一个370M的文件

–场景2:三个线程同时拷贝,每个线程拷贝一个370M文件

场景

FileInputStream+

FileOutputStream

FileInputStream+

BufferedInputStream+

FileOutputStream

ByteBuffer+

FileChannel

MappedByteBuffer

+FileChannel

场景一时间( 毫秒 )                 

25155

17500

19000

16500

场景二时间( 毫秒 )

69000

67031

74031

71016

5.nio.charset

字符编码解码:字节码本身只是一些数字,放到正确的上下文中被正确解析。向ByteBuffer中存放数据时需要考虑字符集的编码方式,读取展示ByteBuffer数据时涉及对字符集解码。

Java.nio.charset提供了编码解码一套解决方案。

以我们最常见的http请求为例,在请求时必须对请求进行正确的编码。在得到响应时必须对响应进行正确的解码。

以下代码向baidu发一次请求,并获取结果进行显示。例子演示了charset的使用。

例子2BaiduReader.java

package nio.readpage;
import java.nio.ByteBuffer;
import java.nio.channels.SocketChannel;
import java.nio.charset.Charset;
import java.net.InetSocketAddress;
import java.io.IOException;
public class BaiduReader {
	private Charset charset = Charset.forName("GBK");
	// 创建GBK字符集 
	private SocketChannel channel;
	public void readHTMLContent() {
		try {
			InetSocketAddress socketAddress = new InetSocketAddress( 
			"www.baidu.com", 80);
			//step1:打开连接 
			channel = SocketChannel.open(socketAddress);
			//step2:使用GBK编码发送请求 
			channel.write(charset.encode("GET " + "/ HTTP/1.1" + "\r\n\r\n"));
			//step3:データの読み取り 
			ByteBuffer buffer = ByteBuffer.allocate(1024);
			// 作成1024バイトのバッファ 
			while (channel.read(buffer) != -1) {
				buffer.flip();
				// flipメソッドは読み取りバッファのバイト操作前に呼び出されます。 
				System.out.println(charset.decode(buffer));
				// Charset.decodeメソッドを使用してバイトを文字列に変換 
				buffer.clear();
				// バッファをクリア
			}
		}
		catch (IOException e) {
			System.err.println(e.toString());
		}
		finally {
			if (channel != null) {
				try {
					channel.close();
				}
				catch (IOException e) {
				}
			}
		}
	}
	public static void main(String[] args) {
		new BaiduReader().readHTMLContent();
	}
}

6.非ブロッキングIO

非ブロッキングIOについて、ブロッキングとは何か、非ブロッキングとは何か、非ブロッキングの原理、アシンクリーナークエア核心APIのいくつかの面から理解します。

ブロッキングとは何か?

一般的なネットワークIO通信プロセスは以下のようになります:

このネットワーク通信プロセスを通じて、ブロッキングとは何かを理解しましょう:

上記のプロセスで接続がまだ来ていない場合、acceptがブロッキングされます。プログラムがこの地点に達すると、プログラムは停止し、CPUは他のスレッドを実行します。

上記のプロセスでデータが準備できていない場合、readもブロッキングされます。

ブロッキング式ネットワークIOの特徴:マルチスレッドで複数の接続を処理します。各スレッドは独自のスタックスペースを持ち、CPU時間を占有します。各スレッドが外部が準備できていない場合、ブロッキングされます。ブロッキングの結果として、多くのプロセスコンテキストの切り替えが発生します。多くの切り替えは無意味です。例えば、あるスレッドがポートをリスニングし、一日に数回だけリクエストが来る場合でも、そのCPUはそのスレッドに対して絶えずコンテキスト切り替えを試みますが、多くの切り替えはブロッキングで終わります。

非ブロッキングとは何か?

以下に比喩を挙げます:

AからBへの公共バスに、途中で降車する場所がたくさんあります。運転手はどの地点で誰が降車するか知りません。降車する必要がある乗客に対して、どのように処理するのが良いのでしょうか?

1運転手は途中でそれぞれの乗客に目的地に到着したかどうかを尋ねます。誰かが到着したと答えたら、運転手は車を止め、乗客が降車します。(ブロッキングに似ています)

2乗客はそれぞれの目的地を售票員に伝え、その後寝ます。運転手は售票員とのみ交渉し、ある場所に到着すると售票員が乗客に降車を知らせます。(非ブロッキングに似ています)

明らかに、誰かが特定の目的地に到達するのはスレッドと考えて、運転手はCPUと考えられます。ブロッキング方式では、各スレッドは不断にループし、上下文切り替えを行い、目的地に到達する結果を達成する必要があります。一方、非ブロッキング方式では、各乗客(スレッド)は眠り(スリープ)しており、外部環境が準備ができ次第のみ唤醒され、この唤醒はブロックされることはありません。

非ブロッキングの原理

全体のプロセスを小さなタスクに切り替え、タスク間の協力で完了します。

特別なスレッドがすべてのIOイベントを処理し、配信を担当します。

イベント駆動メカニズム:イベントが発生したときにトリガーします。イベントを同期して監視するのではなく。

スレッド間通信:wait、notifyなどの方法でスレッド間で通信を行い、各上下文切り替えが意味のあるものになるようにします。無駄なプロセス切り替えを減少させます。

以下は非同期IOの構造です:

Reactorは上記の比喩的な售票員役割です。各スレッドの処理フローは、データの読み取り、デコード、計算処理、エンコード、レスポンスの送信などです。

非同期IOの核心API

Selector

非同期IOの核心クラスで、1つまたは複数のチャンネル(channel)上のイベントを検出し、イベントを配信します。

1つのselectスレッドで複数のチャンネル上のイベントを監視し、イベントに基づいて対応するレスポンスをトリガーすることができます。各channelごとにスレッドを割り当てる必要はありません。

SelectionKey

イベントの状態情報と、時間に対応するチャンネルのバインディングが含まれています。

まとめ

これで本文のJava基础知识に関するすべての内容が終わりです。皆様の助けになれば幸いです。興味を持たれた方、他の関連トピックもご覧ください。不足之处があれば、お気軽にご意見ください。皆様のサポートに感謝します。

声明:この記事の内容はインターネットから取得しており、著作権者は所有者であり、インターネットユーザーが自発的に貢献し、自己でアップロードしています。このサイトは所有権を持ちませんし、人工的な編集処理も行っていません。著作権侵害が疑われる内容を見つけた場合は、notice#wまでメールでお知らせください。3codebox.com(メール送信時、#を@に変更してください)で通報し、関連する証拠を提供してください。一旦確認されると、このサイトは即座に侵害疑いのコンテンツを削除します。

おすすめ