溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊(cè)×
其他方式登錄
點(diǎn)擊 登錄注冊(cè) 即表示同意《億速云用戶服務(wù)條款》

Netty NIO的簡(jiǎn)單介紹

發(fā)布時(shí)間:2021-06-26 10:04:09 來源:億速云 閱讀:183 作者:chen 欄目:大數(shù)據(jù)

這篇文章主要介紹“Netty NIO的簡(jiǎn)單介紹”,在日常操作中,相信很多人在Netty NIO的簡(jiǎn)單介紹問題上存在疑惑,小編查閱了各式資料,整理出簡(jiǎn)單好用的操作方法,希望對(duì)大家解答”Netty NIO的簡(jiǎn)單介紹”的疑惑有所幫助!接下來,請(qǐng)跟著小編一起來學(xué)習(xí)吧!

1. 傳統(tǒng)IO(BIO)存在的問題

同步阻塞

    也就是傳統(tǒng)IO(也就是InputStream、OutputStream等Java中IO包下的類以及 java.net下面提供的部分網(wǎng)絡(luò) API,比如 Socket、ServerSocket、HttpURLConnection 也歸類到同步阻塞 IO 類庫,因?yàn)榫W(wǎng)絡(luò)通信同樣是 IO 行為。)在進(jìn)行讀寫操作(調(diào)用read/write方法)時(shí)會(huì)停止當(dāng)前線程,使得當(dāng)前線程進(jìn)入阻塞狀態(tài),直到讀寫操作結(jié)束后,線程才能繼續(xù)執(zhí)行。

    傳統(tǒng)IO的同步阻塞問題導(dǎo)致了其在性能上的極大缺陷,因?yàn)槊恳粋€(gè)線程在同一時(shí)刻只能管理(運(yùn)行)一個(gè)IO流,尤其是對(duì)于網(wǎng)絡(luò)應(yīng)用程序來說,如果采用傳統(tǒng)IO方式,那么只能一個(gè)線程管理持有一個(gè)IO流,這對(duì)于系統(tǒng)來說并發(fā)情況下的性能瓶頸就太大了,代碼如下所示

import java.io.IOException;
import java.io.InputStream;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
/**
 * 傳統(tǒng)socket服務(wù)端
 *
 */
public class ioServer {

	@SuppressWarnings("resource")
	public static void main(String[] args) throws Exception {

		ExecutorService newCachedThreadPool = Executors.newCachedThreadPool();
		//創(chuàng)建socket服務(wù),監(jiān)聽10101端口
		ServerSocket server=new ServerSocket(10101);
		System.out.println("服務(wù)器啟動(dòng)!");
		while(true){
			//獲取一個(gè)套接字(阻塞)
			final Socket socket = server.accept();
			System.out.println("來個(gè)一個(gè)新客戶端!");
			newCachedThreadPool.execute(new Runnable() {
				
				@Override
				public void run() {
					//業(yè)務(wù)處理
					handler(socket);
				}
			});
			
		}
	}
	
	/**
	 * 讀取數(shù)據(jù)
	 * @param socket
	 * @throws Exception
	 */
	public static void handler(Socket socket){
			try {
				byte[] bytes = new byte[1024];
				InputStream inputStream = socket.getInputStream();
				
				while(true){
					//讀取數(shù)據(jù)(阻塞)
					int read = inputStream.read(bytes);
					if(read != -1){
						System.out.println(new String(bytes, 0, read));
					}else{
						break;
					}
				}
			} catch (Exception e) {
				e.printStackTrace();
			}finally{
				try {
					System.out.println("socket關(guān)閉");
					socket.close();
				} catch (IOException e) {
					e.printStackTrace();
				}
			}
	}
}

    如果使用傳統(tǒng)IO方式,那么就必須為每一個(gè)連接到服務(wù)端的客戶端建立一個(gè)線程來處理IO,并發(fā)量低的時(shí)候還好,可是一旦并發(fā)量極高,造成創(chuàng)建大量線程,就會(huì)導(dǎo)致非常頻繁的進(jìn)行線程間切換,這對(duì)系統(tǒng)性能消耗極大,而且線程切換是無用的消耗。

同步和阻塞是有區(qū)別的,它們的修飾對(duì)象是不同的。

阻塞和非阻塞是指進(jìn)程訪問的數(shù)據(jù)如果尚未就緒,進(jìn)程是否需要等待,簡(jiǎn)單說這相當(dāng)于函數(shù)內(nèi)部的實(shí)現(xiàn)區(qū)別,也就是未就緒時(shí)是直接返回還是等待就緒。
同步和異步是指訪問數(shù)據(jù)的機(jī)制,同步一般指主動(dòng)請(qǐng)求并等待I/O操作完畢的方式,當(dāng)數(shù)據(jù)就緒后在讀寫的時(shí)候必須阻塞,異步則指主動(dòng)請(qǐng)求數(shù)據(jù)后便可以繼續(xù)處理其它任務(wù),隨后等待I/O,操作完畢的通知,這可以使進(jìn)程在數(shù)據(jù)讀寫時(shí)也不阻塞。

2. NIO(AIO)

異步非阻塞

    為了改善傳統(tǒng)IO的問題,在 Java 1.4 中引入了 NIO 框架(java.nio 包),提供了 Channel、Selector、Buffer 等新的類,可以構(gòu)建多路復(fù)用的、同步非阻塞 IO 程序,同時(shí)提供了更接近操作系統(tǒng)底層的高性能數(shù)據(jù)操作方式。在 Java 7 中,NIO 有了進(jìn)一步的改進(jìn),也就是 NIO 2,引入了異步非阻塞 IO 方式,也有很多人叫它 AIO(Asynchronous IO)。異步 IO 操作基于事件和回調(diào)機(jī)制,可以簡(jiǎn)單理解為,讀寫操作直接返回,而不會(huì)阻塞在那里,當(dāng)后臺(tái)處理完成,操作系統(tǒng)會(huì)通知相應(yīng)線程進(jìn)行后續(xù)工作,并發(fā)性能再次提升。針對(duì)

NIO核心實(shí)現(xiàn)類

    Java中為NIO提供三個(gè)核心實(shí)現(xiàn)類,主要是緩沖區(qū)(Buffer)、通道(Channel)、選擇器(Selector)。

1. 通道(Channel)

    1. 通道(Channel):原本在傳統(tǒng)IO中是通過流來進(jìn)行讀寫操作,但是在NIO中是采用Channel來進(jìn)行讀寫操作,Channel替代了傳統(tǒng)IO中的流。

    2. Java中提供了Channel的幾種具體實(shí)現(xiàn)類,這些通道涵蓋了UDP 和 TCP 網(wǎng)絡(luò)IO,以及文件IO。

  • FileChannel:文件IO

  • DatagramChannel:UDP網(wǎng)絡(luò)IO

  • SocketChannel:TCP客戶端網(wǎng)絡(luò)IO

  • ServerSocketChannel:TCP服務(wù)端網(wǎng)絡(luò)IO

Netty NIO的簡(jiǎn)單介紹

    3. Channel有三個(gè)特點(diǎn):

  • Channel是可讀可寫的,但是一個(gè)Channel要么只能寫要么只能讀

  • Channel可以異步的讀和寫

  • 數(shù)據(jù)總是從Channel中讀到Buffer,或者從Buffer中寫到Channel

2. 緩沖區(qū)(Buffer)

    1. Channel負(fù)責(zé)讀寫數(shù)據(jù),而緩沖區(qū)Buffer則負(fù)責(zé)臨時(shí)保存Channel讀寫的數(shù)據(jù),也就是緩存數(shù)據(jù),所有的數(shù)據(jù)都會(huì)經(jīng)過Buffer寫入到Channel或者從Channel中讀取存儲(chǔ)到Buffer。JavaNIO中為Buffer提供了所有基本數(shù)據(jù)類型的實(shí)現(xiàn)類,覆蓋了你能通過IO發(fā)送的基本數(shù)據(jù)類型:byte, short, int, long, float, double 和 char。還有另外一個(gè)MappedByteBuffer。

  • ByteBuffer

  • CharBuffer

  • DoubleBuffer

  • FloatBuffer

  • IntBuffer

  • LongBuffer

  • ShortBuffer

3. 選擇器(Selector)

    1. 傳統(tǒng)IO因?yàn)橐粋€(gè)線程對(duì)應(yīng)一個(gè)IO的局限導(dǎo)致其在高并發(fā)下的性能浪費(fèi),而NIO中則因?yàn)镾elector的存在實(shí)現(xiàn)了允許一個(gè)單獨(dú)的線程來監(jiān)視多個(gè)輸入通道,你可以注冊(cè)多個(gè)通道使用一個(gè)選擇器,然后使用一個(gè)單獨(dú)的線程來“選擇”通道:這些通道里已經(jīng)有可以處理的輸入,或者選擇已準(zhǔn)備寫入的通道。這種選擇機(jī)制,使得一個(gè)單獨(dú)的線程很容易來管理多個(gè)通道。

要使用Selector,得向Selector注冊(cè)Channel,然后調(diào)用它的select()方法。這個(gè)方法會(huì)一直阻塞到某個(gè)注冊(cè)的通道有事件就緒。一旦這個(gè)方法返回,線程就可以處理這些事件,事件的例子有如新連接進(jìn)來,數(shù)據(jù)接收等。

Netty NIO的簡(jiǎn)單介紹

到此,關(guān)于“Netty NIO的簡(jiǎn)單介紹”的學(xué)習(xí)就結(jié)束了,希望能夠解決大家的疑惑。理論與實(shí)踐的搭配能更好的幫助大家學(xué)習(xí),快去試試吧!若想繼續(xù)學(xué)習(xí)更多相關(guān)知識(shí),請(qǐng)繼續(xù)關(guān)注億速云網(wǎng)站,小編會(huì)繼續(xù)努力為大家?guī)砀鄬?shí)用的文章!

向AI問一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權(quán)請(qǐng)聯(lián)系站長郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI